Zeile "Erneut prüfen" in Abfrageplänen mit einem Bitmap-Index-Scan

21

Dies ist eine Abspaltung von Kommentaren zur vorherigen Frage:

Bei Verwendung von PostgreSQL 9.4 scheint es Recheck Cond:in Abfrageplänen, die von ausgegeben werden , immer eine Zeile nach Bitmap-Index-Scans zu geben EXPLAIN.

Wie in der EXPLAINAusgabe der referenzierten Frage:

->  Bitmap Heap Scan on table_three  (cost=2446.92..19686.74 rows=8159 width=7)
      Recheck Cond: (("timestamp" > (now() - '30 days'::interval)) AND (client_id > 0))
      ->  BitmapAnd  (cost=2446.92..2446.92 rows=8159 width=0)
            ->  Bitmap Index Scan on table_one_timestamp_idx  (cost=0.00..1040.00 rows=79941 width=0)
                  Index Cond: ("timestamp" > (now() - '30 days'::interval))
            ->  Bitmap Index Scan on fki_table_three_client_id  (cost=0.00..1406.05 rows=107978 width=0)
                  Index Cond: (client_id > 0)

Oder in der Ausgabe von EXPLAIN ANALYZEfür eine einfache, große Tabelle (mit sehr wenig work_mem):

EXPLAIN ANALYZE SELECT * FROM aa WHERE a BETWEEN 100000 AND 200000;
Bitmap Heap Scan on aa  (cost=107.68..4818.05 rows=5000 width=4) (actual time=27.629..213.606 rows=100001 loops=1)
  Recheck Cond: ((a >= 100000) AND (a <= 200000))
  Rows Removed by Index Recheck: 758222
  Heap Blocks: exact=693 lossy=3732
  ->  Bitmap Index Scan on aai  (cost=0.00..106.43 rows=5000 width=0) (actual time=27.265..27.265 rows=100001 loops=1)
        Index Cond: ((a >= 100000) AND (a <= 200000))

Müssen die Indexbedingungen nach einem Bitmap-Index-Scan ein zweites Mal überprüft werden?
Was können wir noch aus der EXPLAINAusgabe lernen ?

Erwin Brandstetter
quelle

Antworten:

17

Als @Chris die referenzierte Frage richtig kommentierte :

Eine kleine Untersuchung scheint darauf hinzudeuten, dass die Neuüberprüfungsbedingung immer im gedruckt wird. Sie EXPLAINwird jedoch nur dann ausgeführt, wenn work_memdie Bitmap klein genug ist, um Verluste zu verursachen. Gedanken? http://www.postgresql.org/message-id/[email protected]

Während dies alles zutrifft und der Kernentwickler Heikki Linnakangas eine erstklassige Quelle ist, stammt der Beitrag aus dem Jahr 2007 (Postgres 8.2). Hier ist ein Blog-Beitrag von Michael Paquier mit detaillierten Erläuterungen zu Postgres 9.4 , in dem die Ausgabe von EXPLAIN ANALYZEmit mehr Informationen verbessert wurde.

Bei Bitmap-Index-Scans Recheck Cond:ist die Zeile immer vorhanden. Die Ausgabe von basic EXPLAINwird uns nicht mehr verraten. Zusätzliche Informationen erhalten wir aus EXPLAIN ANALYZEdem zweiten Zitat in der Frage:

Heap Blocks: exact=693 lossy=3732

Von insgesamt 4425 Datenseiten (Blöcken) wurden 693 Tupel genau gespeichert (einschließlich Tupelzeiger), während die anderen 3732 Seiten (nur die Datenseite) in der Bitmap verlustbehaftet waren . Das passiert, wenn work_memnicht groß genug ist, um die gesamte Bitmap, die aus dem Index-Scan erstellt wurde, genau zu speichern (verlustfrei).

Die Indexbedingung muss für Seiten aus der verlustbehafteten Freigabe erneut überprüft werden, da die Bitmap nur die abzurufenden Seiten und nicht die genauen Tupel auf der Seite speichert. Nicht alle Tupel auf der Seite notwendigerweise die Index Bedingungen passieren, es ist notwendig , um tatsächlich die Bedingung erneut prüfen.

Dies ist der Thread für pgsql-Hacker, in dem der neue Zusatz besprochen wurde . Der Autor Etsuro Fujita bietet eine Formel zur Berechnung des Minimums work_mem, um verlustbehaftete Bitmap-Einträge und nachfolgende Zustandsüberprüfungen zu vermeiden. Die Berechnung ist für komplexe Fälle mit mehreren Bitmap-Scans nicht zuverlässig und wurde daher nicht zur Ausgabe von tatsächlichen Zahlen verwendet EXPLAIN. Es kann immer noch als Schätzung für einfache Fälle dienen.

Zusätzliche Zeile BUFFERS:

Außerdem wird beim Ausführen mit der BUFFERSOption: eine EXPLAIN (ANALYZE, BUFFERS) ...weitere Zeile wie folgt hinzugefügt:

Buffers: shared hit=279 read=79

Dies gibt an, wie viel von der zugrunde liegenden Tabelle (und dem Index) aus dem Cache ( shared hit=279) gelesen wurde und wie viel von der Festplatte ( read=79) abgerufen werden musste . Wenn Sie die Abfrage wiederholen, wird der Teil "Lesen" normalerweise für nicht zu große Abfragen ausgeblendet, da jetzt nach dem ersten Aufruf alles zwischengespeichert wird. Beim ersten Aufruf erfahren Sie, wie viel bereits zwischengespeichert wurde. Nachfolgende Aufrufe zeigen, wie viel Ihr Cache (derzeit) verarbeiten kann.

Es gibt mehr Möglichkeiten. Das Handbuch zur BUFFERSOption:

Geben Sie insbesondere an, wie viele gemeinsam genutzte Blöcke getroffen, gelesen, verschmutzt und geschrieben wurden, wie viele lokale Blöcke getroffen, gelesen, verschmutzt und geschrieben wurden und wie viele temporäre Blöcke gelesen und geschrieben wurden.

Lesen Sie weiter, es gibt noch mehr.
Hier ist die Liste der Ausgabeoptionen im Quellcode .

Erwin Brandstetter
quelle
10

Erwin, da dies unsere Diskussion im Kommentarthread von vorhin war, habe ich mich dazu entschlossen, noch ein bisschen weiter zu stöbern ...

Ich habe eine sehr einfache Abfrage aus einer relativ großen Tabelle. Normalerweise habe ich genug work_mem, aber in diesem Fall habe ich die Befehle verwendet

SET work_mem = 64;

eine sehr kleine work_memund

SET work_mem = default;

um mir den work_memRücken zu kehren, um für meine Anfrage groß genug zu sein.

EXPLAIN & Recheck Condition

Also läuft meine Abfrage nur mit EXPLAINas

EXPLAIN 
SELECT * FROM olap.reading_facts
WHERE meter < 20;

Ich habe die Ergebnisse sowohl für niedrig als auch für hoch erhalten work_mem:

Niedrig work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Hoch work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32)
  Recheck Cond: (meter < 20)
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0)
        Index Cond: (meter < 20)

Lange EXPLAINRede kurzer Sinn, denn der Abfrageplan zeigt erwartungsgemäß an, dass eine erneute Überprüfung möglich ist, aber wir können nicht wissen, ob tatsächlich eine Berechnung durchgeführt wird.

ANALYSE ERKLÄREN & Zustand erneut prüfen

Wenn wir ANALYZEin die Abfrage einbeziehen, teilen uns die Ergebnisse mehr mit, was wir wissen müssen.

Niedrig work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=3.130..13.946 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Rows Removed by Index Recheck: 86727
  Heap Blocks: exact=598 lossy=836
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=3.066..3.066 rows=51840 loops=1)
        Index Cond: (meter < 20)

Hoch work_mem

Bitmap Heap Scan on reading_facts  (cost=898.92..85632.60 rows=47804 width=32) (actual time=2.647..7.247 rows=51840 loops=1)
  Recheck Cond: (meter < 20)
  Heap Blocks: exact=1434
  ->  Bitmap Index Scan on idx_meter_reading_facts  (cost=0.00..886.96 rows=47804 width=0) (actual time=2.496..2.496 rows=51840 loops=1)
        Index Cond: (meter < 20)

Wie erwartet ANALYZEenthüllt uns die Aufnahme einiger sehr wichtiger Informationen. Im unteren work_memFall sehen wir, dass durch die erneute Indexprüfung Zeilen entfernt wurden und dass wir lossyHeap-Blöcke haben.

Fazit? (oder deren Fehlen)

Leider scheint es EXPLAINallein nicht ausreichend zu sein, zu wissen, ob eine erneute Überprüfung des Index tatsächlich erforderlich ist, da einige der Zeilen-IDs zugunsten der Beibehaltung von Seiten während des Bitmap-Heap-Scans gelöscht werden.

Die Verwendung von EXPLAIN ANALYZEist für die Diagnose von Problemen mit Abfragen mittlerer Länge in Ordnung. Wenn die Ausführung einer Abfrage jedoch sehr lange dauert EXPLAIN ANALYZE, work_memist es immer noch schwierig, festzustellen , dass der Bitmap-Index aufgrund unzureichender Daten in einen verlustbehafteten Index konvertiert wird. Ich wünschte, es gäbe eine Möglichkeit, EXPLAINdie Wahrscheinlichkeit dieses Auftretens aus der Tabellenstatistik abzuschätzen.

Chris
quelle