TL; DR: Wenn ein "EXPLAIN (BUFFERS)" einen "Index Scan" anzeigt, wird nicht die Anzahl der Seiten angezeigt, die aus dem Index gelesen werden müssen. Lässt es nur diese Nummer weg oder liest es tatsächlich keine Seiten (und ich verstehe falsch, wie der Index funktioniert)?
Wir haben eine große schreibgeschützte Tabelle, die so aussieht:
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)
und eine typische Abfrage für diese Tabelle hat eine EXPLAIN wie diese ...
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)
So analysiere ich das:
- Die Abfrage führt einen "Bitmap-Index-Scan" durch, bei dem 32 Seiten gelesen werden müssen. Bisher habe ich angenommen, dass diese 32 Seiten die Daten für den Index selbst enthalten. Am Ende wird eine Liste der zu lesenden Seiten erstellt.
- Die Abfrage führt dann den "Bitmap-Heap-Scan" durch, bei dem die Seiten gelesen und dann gelesen werden. Am Ende liest dies über 10.000 Seiten.
Wir haben diese (schreibgeschützte) Tabelle kürzlich in ihrem Index in CLUSTER geändert, wodurch die Anzahl der zu lesenden Seiten drastisch reduziert wurde. Jetzt sieht eine Erklärung so aus ...
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)
In diesem Fall wird ein Index-Scan durchgeführt. Soweit ich weiß, besteht der Unterschied zwischen einem Index-Scan und einem Bitmap-Index / Heap-Scan darin, dass erstere Seiten in der durch den Index definierten Reihenfolge lesen, während letztere eine Bitmap von zu lesenden Seiten erstellen (möglicherweise aus mehreren Indizes) ), bestellen Sie die Ergebnisse und lesen Sie sie der Reihe nach. Es scheint mir, dass man in beiden Fällen die Seiten des Index lesen müsste, um die resultierenden zu lesenden Datenseiten tatsächlich zu bestimmen.
Im "Index-Scan" hat die Zeile für "Puffer" jedoch 160 Seiten. Dies basiert auf meinen anderen Tests auf der Anzahl der Seiten der tatsächlichen Daten und enthält nicht die 32 Seiten, die ich oben im Bitmap-Index-Scan für gesehen habe der Index selbst.
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)
Bedeutet dies, dass der Index-Scan nicht tatsächlich aus dem Index liest? Woher weiß es dann, welche Seiten zu lesen sind? Wird die Anzahl der gelesenen Indexseiten in der Erläuterungsausgabe des Index-Scans einfach weggelassen? Oder vielleicht ist mein Verständnis dessen, was dieser Wert im Bitmap-Index-Scan darstellt, falsch.