Chơi một chút với pg_buffercache , tôi có thể nhận được câu trả lời cho một số câu hỏi của bạn.
- Điều này khá rõ ràng, nhưng kết quả cho (5) cũng cho thấy câu trả lời là CÓ
- Tôi vẫn chưa thiết lập một ví dụ tốt cho việc này, vì bây giờ nó có nhiều hơn không :) (Xem phần chỉnh sửa của tôi bên dưới, câu trả lời là KHÔNG .)
- Vì người lập kế hoạch là người quyết định có sử dụng chỉ mục hay không, chúng tôi có thể nói CÓ , nó quyết định bộ nhớ đệm (nhưng điều này phức tạp hơn)
- Các chi tiết chính xác của bộ nhớ đệm có thể được lấy từ mã nguồn, tôi không thể tìm thấy quá nhiều về chủ đề này, ngoại trừ cái này (cũng xem câu trả lời của tác giả ). Tuy nhiên, tôi khá chắc chắn rằng điều này một lần nữa phức tạp hơn nhiều so với đơn giản có hoặc không. (Một lần nữa, từ chỉnh sửa của tôi bạn có thể nhận được một số ý tưởng - vì kích thước bộ nhớ cache được giới hạn, những chỉ số 'nhạy cảm' cạnh tranh cho không gian có sẵn Nếu họ quá nhiều, họ sẽ đá với nhau từ bộ nhớ cache -. Nên câu trả lời là khá NO . )
- Là một truy vấn đơn giản với các
pg_buffercache
chương trình, câu trả lời là CÓ CÓ . Điều đáng lưu ý là dữ liệu bảng tạm thời không được lưu vào bộ nhớ cache ở đây.
BIÊN TẬP
Tôi đã tìm thấy bài viết tuyệt vời của Jeremiah Peschka về lưu trữ bảng và chỉ mục. Với thông tin từ đó, tôi cũng có thể trả lời (2) . Tôi thiết lập một thử nghiệm nhỏ, để bạn có thể tự kiểm tra chúng.
-- we will need two extensions
CREATE EXTENSION pg_buffercache;
CREATE EXTENSION pageinspect;
-- a very simple test table
CREATE TABLE index_cache_test (
id serial
, blah text
);
-- I am a bit megalomaniac here, but I will use this for other purposes as well
INSERT INTO index_cache_test
SELECT i, i::text || 'a'
FROM generate_series(1, 1000000) a(i);
-- let's create the index to be cached
CREATE INDEX idx_cache_test ON index_cache_test (id);
-- now we can have a look at what is cached
SELECT c.relname,count(*) AS buffers
FROM
pg_class c
INNER JOIN pg_buffercache b ON b.relfilenode = c.relfilenode
INNER JOIN pg_database d ON (b.reldatabase = d.oid AND d.datname = current_database())
GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10;
relname | buffers
----------------------------------+---------
index_cache_test | 2747
pg_statistic_relid_att_inh_index | 4
pg_operator_oprname_l_r_n_index | 4
... (others are all pg_something, which are not interesting now)
-- this shows that the whole table is cached and our index is not in use yet
-- now we can check which row is where in our index
-- in the ctid column, the first number shows the page, so
-- all rows starting with the same number are stored in the same page
SELECT * FROM bt_page_items('idx_cache_test', 1);
itemoffset | ctid | itemlen | nulls | vars | data
------------+---------+---------+-------+------+-------------------------
1 | (1,164) | 16 | f | f | 6f 01 00 00 00 00 00 00
2 | (0,1) | 16 | f | f | 01 00 00 00 00 00 00 00
3 | (0,2) | 16 | f | f | 02 00 00 00 00 00 00 00
4 | (0,3) | 16 | f | f | 03 00 00 00 00 00 00 00
5 | (0,4) | 16 | f | f | 04 00 00 00 00 00 00 00
6 | (0,5) | 16 | f | f | 05 00 00 00 00 00 00 00
...
64 | (0,63) | 16 | f | f | 3f 00 00 00 00 00 00 00
65 | (0,64) | 16 | f | f | 40 00 00 00 00 00 00 00
-- with the information obtained, we can write a query which is supposed to
-- touch only a single page of the index
EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM index_cache_test
WHERE id BETWEEN 10 AND 20 ORDER BY id
;
Index Scan using idx_test_cache on index_cache_test (cost=0.00..8.54 rows=9 width=4) (actual time=0.031..0.042 rows=11 loops=1)
Index Cond: ((id >= 10) AND (id <= 20))
Buffers: shared hit=4
Total runtime: 0.094 ms
(4 rows)
-- let's have a look at the cache again (the query remains the same as above)
relname | buffers
----------------------------------+---------
index_cache_test | 2747
idx_test_cache | 4
...
-- and compare it to a bigger index scan:
EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM index_cache_test
WHERE id <= 20000 ORDER BY id
;
Index Scan using idx_test_cache on index_cache_test (cost=0.00..666.43 rows=19490 width=4) (actual time=0.072..19.921 rows=20000 loops=1)
Index Cond: (id <= 20000)
Buffers: shared hit=4 read=162
Total runtime: 24.967 ms
(4 rows)
-- this already shows that something was in the cache and further pages were read from disk
-- but to be sure, a final glance at cache contents:
relname | buffers
----------------------------------+---------
index_cache_test | 2691
idx_test_cache | 58
-- note that some of the table pages are disappeared
-- but, more importantly, a bigger part of our index is now cached
Nói chung, điều này cho thấy các chỉ mục và bảng có thể được lưu vào bộ đệm theo từng trang, do đó câu trả lời cho (2) là KHÔNG .
Và một cái cuối cùng để minh họa các bảng tạm thời không được lưu trong bộ nhớ cache ở đây:
CREATE TEMPORARY TABLE tmp_cache_test AS
SELECT * FROM index_cache_test ORDER BY id FETCH FIRST 20000 ROWS ONLY;
EXPLAIN (ANALYZE, BUFFERS) SELECT id FROM tmp_cache_test ORDER BY id;
-- checking the buffer cache now shows no sign of the temp table