Este é um desdobramento dos comentários da pergunta anterior:
Usando o PostgreSQL 9.4, sempre parece haver uma Recheck Cond:
linha após as varreduras de índice de bitmap nos planos de consulta gerados por arquivos EXPLAIN
.
Como na EXPLAIN
saída da pergunta referenciada:
-> 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 na saída de EXPLAIN ANALYZE
uma tabela enorme e simples (com muito pouco 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))
Isso significa que as condições de índice devem ser verificadas uma segunda vez após uma varredura de índice de bitmap?
O que mais podemos aprender com a EXPLAIN
saída?
Como @Chris comentou corretamente na questão referenciada :
Embora tudo isso seja verdade e o desenvolvedor central Heikki Linnakangas seja uma fonte de primeira classe, o post data de 2007 (Postgres 8.2). Aqui está uma postagem no blog de Michael Paquier com uma explicação detalhada do Postgres 9.4 , onde a saída
EXPLAIN ANALYZE
foi aprimorada com mais informações.A
Recheck Cond:
linha está sempre presente para varreduras de índice de bitmap. A saída de basicEXPLAIN
não nos dirá mais. Obtemos informações adicionais deEXPLAIN ANALYZE
como pode ser visto na segunda citação na pergunta:De um total de 4.425 páginas de dados (blocos), 693 tuplas foram armazenadas exatamente (incluindo ponteiros de tupla), enquanto as outras 3.732 páginas tiveram perdas (apenas a página de dados) no bitmap. Isso acontece quando
work_mem
não é grande o suficiente para armazenar todo o bitmap construído a partir da varredura de índice exatamente (sem perdas).A condição do índice deve ser verificada novamente para páginas do compartilhamento com perdas, pois o bitmap lembra apenas quais páginas buscar e não as tuplas exatas na página. Nem todas as tuplas na página passarão necessariamente pelas condições do índice, é necessário verificar novamente a condição.
Este é o tópico sobre hackers pgsql onde a nova adição foi discutida . O autor Etsuro Fujita fornece uma fórmula de como calcular o mínimo
work_mem
para evitar entradas de bitmap com perdas e verificações de condição subsequentes. O cálculo não é confiável para casos complexos com várias varreduras de bitmap, portanto, não foi usado para gerar números reais deEXPLAIN
. Ainda pode servir como estimativa para casos simples.Linha adicional
BUFFERS:
Além disso, ao executar com a
BUFFERS
opção:EXPLAIN (ANALYZE, BUFFERS) ...
outra linha é adicionada como:Isso indica quanto da tabela subjacente (e índice) foi lido do cache (
shared hit=279
) e quanto teve que ser obtido do disco (read=79
). Se você repetir a consulta, a parte "lida" normalmente desaparece para consultas não muito grandes, porque tudo é armazenado em cache agora após a primeira chamada. A primeira chamada informa quanto já foi armazenado em cache. As chamadas subseqüentes mostram quanto seu cache pode suportar (atualmente).Existem mais opções. O manual sobre a
BUFFERS
opção:Leia, há mais.
Aqui está a lista de opções de saída no código-fonte .
Erwin, já que essa foi a nossa discussão no tópico de comentários anterior, decidi cutucar um pouco mais...
Eu tenho uma consulta muito simples de uma tabela de tamanho razoável. Eu normalmente tenho o suficiente
work_mem
, mas neste caso usei os comandospara definir um muito pequeno
work_mem
epara definir minhas
work_mem
costas para ser suficientemente grande para minha consulta.EXPLICAR e verificar novamente a condição
Então, executando minha consulta com
EXPLAIN
apenasEu obtive os resultados para baixo e alto
work_mem
:Baixo
work_mem
Alto
work_mem
Para encurtar a história,
EXPLAIN
apenas, como esperado, o plano de consulta indica que uma condição Recheck é possível, mas não podemos saber se será realmente computada.EXPLICAR ANALISAR E VERIFICAR novamente a condição
Quando incluímos
ANALYZE
na consulta, os resultados nos dizem mais sobre o que precisamos saber.Baixo
work_mem
Alto
work_mem
Novamente, como esperado, a inclusão de
ANALYZE
nos revela algumas informações muito importantes. Nowork_mem
caso baixo, vemos que há linhas removidas pela nova verificação do índice e que temoslossy
blocos de heap.Conclusão? (ou falta dela)
Infelizmente, parece que
EXPLAIN
por si só não é suficiente para saber se uma nova verificação de índice será realmente necessária porque alguns dos IDs de linha estão sendo descartados em favor da retenção de páginas durante a varredura de heap de bitmap.Usar
EXPLAIN ANALYZE
é bom para diagnosticar os problemas com consultas de comprimento moderado, mas no caso de uma consulta levar muito tempo para ser concluída, executarEXPLAIN ANALYZE
para descobrir que seu índice de bitmap está convertendo em com perdas devido a insuficientework_mem
ainda é uma restrição difícil. Eu gostaria que houvesse uma maneira deEXPLAIN
estimar a probabilidade dessa ocorrência a partir das estatísticas da tabela.