pg_buffercache 로 조금만 연주하면 몇 가지 질문에 대한 답변을 얻을 수 있습니다.
- 이것은 명백하지만 (5) 의 결과는 또한 `` 예 '' 라고 대답합니다.
- 나는 이것에 대한 좋은 예를 아직 세우지 않았다. 지금은 아니오보다 그렇다. :) (아래 편집 참조, 대답은 NO )
- 플래너는 인덱스 사용 여부를 결정하는 사람이므로 YES 라고 말하면 캐싱을 결정합니다 (그러나 더 복잡합니다)
- 캐싱에 대한 정확한 세부 사항은 소스 코드에서 파생 될 수 있습니다.이 주제를 제외 하고는 이 주제에서 너무 많이 찾을 수 없었습니다 (저자의 답변 참조 ). 그러나 나는 이것이 단순한 예 또는 아니오보다 훨씬 더 복잡하다는 것을 확신합니다. (내 편집에서 캐시 크기가 제한되어 있기 때문에 해당 '지능적'인 인덱스는 사용 가능한 공간과 경쟁합니다. 너무 많은 경우 캐시에서 서로를 쫓아 낼 수 있으므로 대답은 오히려 NO 입니다. )
- show가 포함 된 간단한 쿼리로서
pg_buffercache
정답은 YES 입니다. 임시 테이블 데이터 는 여기에 캐시 되지 않습니다 .
편집하다
테이블 및 인덱스 스토리지에 대한 Jeremiah Peschka의 훌륭한 기사를 찾았습니다 . 거기에서 정보를 얻음 으로써 나는 (2) 도 대답 할 수 있었다 . 작은 테스트를 설정 했으므로 직접 확인할 수 있습니다.
-- 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
결국 인덱스와 테이블을 페이지별로 캐시 할 수 있으므로 (2)에 대한 답 은 NO 입니다.
그리고 임시 테이블이 캐시되지 않은 것을 설명하는 마지막 테이블은 다음과 같습니다.
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