Ligne "Recheck Cond:" dans les plans de requête avec un scan d'index bitmap


21

Ceci est un spin-off des commentaires à la question précédente:

Avec PostgreSQL 9.4, il semble toujours y avoir une Recheck Cond:ligne après les analyses d'index bitmap dans les plans de requête générés par EXPLAIN.

Comme dans la EXPLAINsortie de la question référencée:

->  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)

Ou dans la sortie de EXPLAIN ANALYZEpour une table simple et immense (avec très peu 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))

Cela signifie-t-il que les conditions d'index doivent être vérifiées une deuxième fois après un balayage d'index bitmap?
Que pouvons-nous apprendre d'autre de la EXPLAINsortie?

Réponses:


17

Comme @Chris l'a correctement commenté sur la question référencée :

une petite enquête semble indiquer que la condition de revérification est toujours imprimée dans le EXPLAIN, mais n'est en fait effectuée que lorsqu'elle work_memest suffisamment petite pour que le bitmap devienne avec perte. Pensées? http://www.postgresql.org/message-id/464F3C5D.2000700@enterprisedb.com

Bien que cela soit vrai et que le développeur principal Heikki Linnakangas soit une source de première classe, la publication remonte à 2007 (Postgres 8.2). Voici un article de blog de Michael Paquier avec une explication détaillée de Postgres 9.4 , où la sortie de EXPLAIN ANALYZEa été améliorée avec plus d'informations.

La Recheck Cond:ligne est toujours là pour les analyses d'index bitmap. La sortie de base EXPLAINne nous en dira pas plus. Nous obtenons des informations supplémentaires EXPLAIN ANALYZEcomme le montre la deuxième citation de la question:

Heap Blocks: exact=693 lossy=3732

Sur un total de 4425 pages de données (blocs), 693 tuples stockés exactement (y compris les pointeurs de tuple), tandis que les autres 3732 pages étaient avec perte (juste la page de données) dans le bitmap. Cela se produit quand work_memn'est pas assez grand pour stocker exactement la totalité du bitmap construit à partir de l'analyse d'index (sans perte).

La condition d'index doit être revérifiée pour les pages du partage avec perte, car le bitmap ne se souvient que des pages à récupérer et non des tuples exacts sur la page. Tous les tuples sur la page passeront nécessairement les conditions d'index, il est nécessaire de fait revérifier la condition.

C'est le fil sur les pirates pgsql où le nouvel ajout a été discuté . L'auteur Etsuro Fujita fournit une formule sur la façon de calculer le minimum work_mempour éviter les entrées bitmap avec perte et les revérifications de condition qui en découlent. Le calcul n'est pas fiable pour les cas complexes avec plusieurs analyses bitmap, il n'a donc pas été utilisé pour générer des nombres réels à partir de EXPLAIN. Il peut encore servir d'estimation pour des cas simples.

Ligne supplémentaire BUFFERS:

De plus, lors de l'exécution avec BUFFERSoption: EXPLAIN (ANALYZE, BUFFERS) ...une autre ligne est ajoutée comme:

Buffers: shared hit=279 read=79

Cela indique la quantité de la table (et de l'index) sous-jacente qui a été lue à partir du cache ( shared hit=279) et combien a dû être récupérée à partir du disque ( read=79). Si vous répétez la requête, la partie "lecture" disparaît généralement pour les requêtes pas trop volumineuses, car tout est mis en cache maintenant après le premier appel. Le premier appel vous indique la quantité déjà mise en cache. Les appels suivants montrent combien votre cache peut gérer (actuellement).

Il y a plus d'options. Le manuel sur l' BUFFERSoption:

Spécifiquement, incluez le nombre de blocs partagés frappés, lus, salis et écrits, le nombre de blocs locaux frappés, lus, salis et écrits et le nombre de blocs temporaires lus et écrits.

Lisez la suite, il y a plus.
Voici la liste des options de sortie dans le code source .


10

Erwin, puisque c'était notre discussion dans le fil de commentaires d'avant, j'ai décidé de pousser un peu plus loin ...

J'ai une requête très simple à partir d'une table de taille raisonnable. J'en ai généralement assez work_mem, mais dans ce cas j'ai utilisé les commandes

SET work_mem = 64;

pour définir un très petit work_memet

SET work_mem = default;

pour me mettre work_memà être suffisamment grand pour ma requête.

EXPLIQUER et revérifier la condition

Donc, ma requête en cours d' exécution avec seulement EXPLAINcomme

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

J'ai obtenu les résultats à la fois bas et haut work_mem:

Faible 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)

Haute 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)

Pour faire court, pour EXPLAINseulement, comme prévu, le plan de requête indique qu'une condition de nouvelle vérification est possible, mais nous ne pouvons pas savoir si elle sera réellement calculée.

EXPLIQUER L'ANALYSE ET REVÉRIFIER LA CONDITION

Lorsque nous incluons ANALYZEdans la requête, les résultats nous en disent plus sur ce que nous devons savoir.

Faible 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)

Haute 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)

Encore une fois, comme prévu, l'inclusion de ANALYZEnous révèle des informations très importantes. Dans le work_memcas bas , nous voyons qu'il y a des lignes supprimées par la vérification de l'index et que nous avons des lossyblocs de tas.

Conclusion? (ou l'absence de)

Malheureusement, il ne semble pas suffisant à lui EXPLAINseul de savoir si une nouvelle vérification de l'index sera réellement nécessaire car certains des ID de ligne sont supprimés au profit de la conservation des pages lors de l'analyse du tas de bitmap.

L'utilisation EXPLAIN ANALYZEest très bien pour diagnostiquer les problèmes avec des requêtes de longueur moyenne, mais dans le cas où une requête prend un temps extrêmement long pour terminer, puis en cours EXPLAIN ANALYZEd' exécution pour découvrir que votre index bitmap se convertit en lossy en raison de l'insuffisance work_memest toujours une contrainte difficile. J'aimerais qu'il y ait un moyen d' EXPLAINestimer la probabilité de cet événement à partir des statistiques du tableau.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.