TL; DR: "EXPLAIN(BUFFERS)"が "Index Scan"を示している場合、インデックスから読み取る必要のあるページ数は示されていません。それは単にその数を省略していますか、それとも実際にページを読み取っていませんか?
次のような大きな読み取り専用テーブルがあります。
database=> \d my_table
Table "my_table"
Column | Type | Modifiers
-----------------------+------------------+-----------
id | integer |
date | date |
country_id | smallint |
...other columns...
Indexes:
"my_table_id_date_idx" btree (id, date)
そして、このテーブルに対する典型的なクエリは、このようなEXPLAINを持っています...
database=> EXPLAIN (BUFFERS, ANALYZE) SELECT id, date, country_id FROM my_table WHERE id = 50 AND date BETWEEN '2015-04-01' AND '2015-04-07';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on my_table (cost=448.40..70400.85 rows=18810 width=10) (actual time=9.011..1447.817 rows=10224 loops=1)
Recheck Cond: ((id = 50) AND (date >= '2015-04-01'::date) AND (date <= '2015-04-07'::date))
Buffers: shared hit=232 read=9994
-> Bitmap Index Scan on my_table_id_date_idx (cost=0.00..443.69 rows=18810 width=0) (actual time=6.467..6.467 rows=10224 loops=1)
Index Cond: ((id = 50) AND (date >= '2015-04-01'::date) AND (date <= '2015-04-07'::date))
Buffers: shared hit=2 read=30
Total runtime: 1450.175 ms
(7 rows)
これが私がこれを分析している方法です:
最近、この(読み取り専用)テーブルをインデックスでCLUSTERに変更しました。これにより、読み取る必要のあるページが劇的に減少しました。これで、説明は次のようになります...
database=> EXPLAIN (BUFFERS, ANALYZE) SELECT id, date, country_id FROM my_table WHERE id = 50 AND date BETWEEN '2015-04-01' AND '2015-04-07';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using my_table_id_date_idx on my_table (cost=0.57..36703.31 rows=20594 width=10) (actual time=0.029..4.830 rows=10224 loops=1)
Index Cond: ((id = 50) AND (date >= '2015-04-01'::date) AND (date <= '2015-04-07'::date))
Buffers: shared hit=160
Total runtime: 6.658 ms
(4 rows)
この場合は、インデックススキャンを実行しています。私が知っている限りでは、インデックススキャンとビットマップインデックス/ヒープスキャンの違いは、前者はインデックスで定義された順序でページを読み取り、後者は読み取るページのビットマップを作成することです(おそらく複数のインデックスから) )、結果を並べ替え、順番に読みます。どちらの場合も、実際に読み取る結果のデータページを決定するには、インデックスのページを読み取る必要があるようです。
ただし、「インデックススキャン」では、「バッファ」の行に160ページあります。これは、他のテストに基づくと、実際のデータのページ数であり、上記のビットマップインデックススキャンで見た32ページが含まれていません。インデックス自体。
database=> set enable_indexscan to false;
SET
database=> EXPLAIN (BUFFERS, ANALYZE) SELECT id, date, country_id FROM my_table WHERE id = 50 AND date BETWEEN '2015-04-01' AND '2015-04-07';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on my_table (cost=491.14..76781.03 rows=20594 width=10) (actual time=1.003..3.873 rows=10224 loops=1)
Recheck Cond: ((id = 50) AND (date >= '2015-04-01'::date) AND (date <= '2015-04-07'::date))
Buffers: shared hit=160
-> Bitmap Index Scan on my_table_id_date_idx (cost=0.00..486.00 rows=20594 width=0) (actual time=0.981..0.981 rows=10224 loops=1)
Index Cond: ((id = 50) AND (date >= '2015-04-01'::date) AND (date <= '2015-04-07'::date))
Buffers: shared hit=32
Total runtime: 5.595 ms
(7 rows)
これは、インデックススキャンが実際にインデックスから読み取られないことを意味しますか?では、どのページを読むべきかをどうやって知るのでしょうか?読み込まれたインデックスページの数は、インデックススキャンのExplain出力で省略されていますか?または、ビットマップインデックススキャンのその値が何を表すかについての私の理解は正しくありません。
この場合は、インデックススキャンを実行しています。私が知っている限りでは、インデックススキャンとビットマップインデックス/ヒープスキャンの違いは、前者はインデックスで定義された順序でページを読み取り、後者は読み取るページのビットマップを作成することです(おそらく複数のインデックスから) )、結果を並べ替え、[ヒープ]順に読み取ります。
正しい。
インデックスのみのスキャンもあり、クエリを直接実行するためにインデックスが読み取られ、読み取られたほとんどのインデックスページにはヒープフェッチがありません。システムがページがすべてのトランザクションから見えることを確認できない場合でも、ヒープフェッチが必要になる場合があるため、ショートカットを使用したインデックススキャンのようなものです。
どちらの場合も、実際に読み取る結果のデータページを決定するには、インデックスのページを読み取る必要があるようです。
正しい。
ただし、「インデックススキャン」では、「バッファ」の行に160ページあります。これは、他のテストに基づくと、実際のデータのページ数であり、上記のビットマップインデックススキャンで見た32ページが含まれていません。インデックス自体。
これは誤解だと思います。その行は、インデックスとヒープから読み取られたページの合計になります。すべてのインデックスページやすべてのヒープページを読み取る必要はありません。
別の重要な注意事項は、EXPLAINの他のメトリックと同様に、「バッファ」メトリックは累積的であるということです。親ノードで読み取られたページの数には、子ノードのページが含まれます。したがって、ヒットした160のバッファには、インデックスの読み取りが含まれます。実際には、最後の両方のケースでヒープから128ページしか読み取られませんでした。