AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 306458
Accepted
Vadim Samokhin
Vadim Samokhin
Asked: 2022-01-24 03:57:59 +0800 CST2022-01-24 03:57:59 +0800 CST 2022-01-24 03:57:59 +0800 CST

Postgresql 10: varredura de heap de bitmap com bloco de heap exato

  • 772

Tenho a seguinte consulta:

select ro.*
from courier c1
    join courier c2 on c2.real_physical_courier_1c_id = c1.real_physical_courier_1c_id
    join restaurant_order ro on ro.courier_id = c2.id
    left join jsonb_array_elements(items) jae on true
    left join jsonb_array_elements(jae->'options') ji on true
    inner join catalogue c on c.id in ((jae->'id')::int, (ji->'id')::int)
    join restaurant r on r.id = ro.restaurant_id
where c1.id = '7b35cdab-b423-472a-bde1-d6699f6cefd3' and ro.status in (70, 73)
group by ro.order_id, r.id ;

Aqui está uma parte de um plano de consulta que leva cerca de 95% do tempo:

->  Parallel Bitmap Heap Scan on restaurant_order ro  (cost=23.87..2357.58 rows=1244 width=1257) (actual time=11.931..38.163 rows=98 loops=2)"
      Recheck Cond: (status = ANY ('{70,73}'::integer[]))"
      Heap Blocks: exact=28755"
      ->  Bitmap Index Scan on ro__status  (cost=0.00..23.34 rows=2115 width=0) (actual time=9.168..9.168 rows=51540 loops=1)"
            Index Cond: (status = ANY ('{70,73}'::integer[]))"

Eu tenho algumas perguntas.

  1. Primeiro, uma seção de verificação de índice de bitmap. O Postgres percorre 51.540 registros de índice ro__status com base Index Cond: (status = ANY ('{70,73}'::integer[]))"e cria um bitmap com 28.755 elementos. Suas chaves são a localização física das linhas da tabela correspondentes (indicadas exactna Heap Blocksseção). Isso está correto?
  2. Segundo, este mapa é passado para a fase Bitmap Heap Scan. Recheck Condnão é realmente executado, pois os blocos de heap não são do estilo com perdas. Bitmap Heap Scan classifica um bitmap pela localização física das tuplas para permitir um acesso sequencial. Em seguida, ele lê os dados da tabela sequencialmente em duas etapas ( loops=2) e não obtém mais de 196 linhas da tabela. Isso é correto?
  3. O tamanho do bitmap refletido na Heap Blocks: exact=28755linha varia muito ao longo do tempo. A diferença é de duas ordens de grandeza. Por exemplo, ontem eram cerca de 500. Por que isso acontece?
  4. Agora, por que um bitmap criado durante a fase de verificação de índice de bitmap tem tantas chaves? Existe um índice ro__status que pode indicar que existem apenas cerca de 200 registros com status 70 e 73. Não consigo pensar em nenhuma razão que impeça o postgres de manter apenas as chaves que realmente satisfazem um index cond. A sobrecarga parece ser enorme: em vez de ~ 200 chaves, existem 28755!
  5. Por que o Bitmap Heap Scan demora tanto? Pelo que vi são duas leituras sequenciais ( loops=2), deve demorar bem menos, não? Ou, a classificação de bitmap pela localização física das tuplas é o principal culpado?
  6. Devo me preocupar com estimativas ruins? Se sim, aumentar default_statistics_target deve ajudar, certo? Agora é o padrão 100.

Apenas no caso, aqui está um plano completo:

"Group  (cost=51297.15..52767.65 rows=19998 width=1261) (actual time=42.555..42.555 rows=0 loops=1)"
"  Group Key: ro.order_id, r.id"
"  ->  Gather Merge  (cost=51297.15..52708.83 rows=11764 width=1261) (actual time=42.554..45.459 rows=0 loops=1)"
"        Workers Planned: 1"
"        Workers Launched: 1"
"        ->  Group  (cost=50297.14..50385.37 rows=11764 width=1261) (actual time=38.850..38.850 rows=0 loops=2)"
"              Group Key: ro.order_id, r.id"
"              ->  Sort  (cost=50297.14..50326.55 rows=11764 width=1261) (actual time=38.850..38.850 rows=0 loops=2)"
"                    Sort Key: ro.order_id, r.id"
"                    Sort Method: quicksort  Memory: 25kB"
"                    Worker 0:  Sort Method: quicksort  Memory: 25kB"
"                    ->  Nested Loop  (cost=31.84..45709.27 rows=11764 width=1261) (actual time=38.819..38.819 rows=0 loops=2)"
"                          ->  Nested Loop Left Join  (cost=27.21..5194.50 rows=5882 width=1325) (actual time=38.819..38.819 rows=0 loops=2)"
"                                ->  Nested Loop Left Join  (cost=27.20..5076.49 rows=59 width=1293) (actual time=38.818..38.818 rows=0 loops=2)"
"                                      ->  Nested Loop  (cost=27.20..5074.49 rows=1 width=1261) (actual time=38.818..38.818 rows=0 loops=2)"
"                                            ->  Hash Join  (cost=26.93..5073.59 rows=1 width=1257) (actual time=38.817..38.818 rows=0 loops=2)"
"                                                  Hash Cond: (c2.real_physical_courier_1c_id = c1.real_physical_courier_1c_id)"
"                                                  ->  Nested Loop  (cost=24.28..5068.22 rows=1038 width=1267) (actual time=11.960..38.732 rows=98 loops=2)"
"                                                        ->  Parallel Bitmap Heap Scan on restaurant_order ro  (cost=23.87..2357.58 rows=1244 width=1257) (actual time=11.931..38.163 rows=98 loops=2)"
"                                                              Recheck Cond: (status = ANY ('{70,73}'::integer[]))"
"                                                              Heap Blocks: exact=28755"
"                                                              ->  Bitmap Index Scan on ro__status  (cost=0.00..23.34 rows=2115 width=0) (actual time=9.168..9.168 rows=51540 loops=1)"
"                                                                    Index Cond: (status = ANY ('{70,73}'::integer[]))"
"                                                        ->  Index Scan using courier_pkey on courier c2  (cost=0.41..2.18 rows=1 width=26) (actual time=0.005..0.005 rows=1 loops=195)"
"                                                              Index Cond: (id = ro.courier_id)"
"                                                  ->  Hash  (cost=2.63..2.63 rows=1 width=10) (actual time=0.039..0.039 rows=1 loops=2)"
"                                                        Buckets: 1024  Batches: 1  Memory Usage: 9kB"
"                                                        ->  Index Scan using courier_pkey on courier c1  (cost=0.41..2.63 rows=1 width=10) (actual time=0.034..0.034 rows=1 loops=2)"
"                                                              Index Cond: (id = '7b35cdab-b423-472a-bde1-d6699f6cefd3'::uuid)"
"                                            ->  Index Only Scan using restaurant_pkey on restaurant r  (cost=0.27..0.89 rows=1 width=4) (never executed)"
"                                                  Index Cond: (id = ro.restaurant_id)"
"                                                  Heap Fetches: 0"
"                                      ->  Function Scan on jsonb_array_elements jae  (cost=0.00..1.00 rows=100 width=32) (never executed)"
"                                ->  Function Scan on jsonb_array_elements ji  (cost=0.01..1.00 rows=100 width=32) (never executed)"
"                          ->  Bitmap Heap Scan on catalogue c  (cost=4.63..6.87 rows=2 width=4) (never executed)"
"                                Recheck Cond: ((id = ((jae.value -> 'id'::text))::integer) OR (id = ((ji.value -> 'id'::text))::integer))"
"                                ->  BitmapOr  (cost=4.63..4.63 rows=2 width=0) (never executed)"
"                                      ->  Bitmap Index Scan on catalogue_pkey  (cost=0.00..0.97 rows=1 width=0) (never executed)"
"                                            Index Cond: (id = ((jae.value -> 'id'::text))::integer)"
"                                      ->  Bitmap Index Scan on catalogue_pkey  (cost=0.00..0.97 rows=1 width=0) (never executed)"
"                                            Index Cond: (id = ((ji.value -> 'id'::text))::integer)"
"Planning Time: 1.113 ms"
"Execution Time: 45.588 ms"
postgresql execution-plan
  • 1 1 respostas
  • 307 Views

1 respostas

  • Voted
  1. Best Answer
    jjanes
    2022-01-24T10:52:58+08:002022-01-24T10:52:58+08:00

    Ele cria um bitmap de 51.540 itens. Este é então dividido (aproximadamente) ao meio, um para cada um dos dois processos paralelos. O relatório de exact=28755é aparentemente para apenas um desses processos. (Se você desabilitar as consultas paralelas por set max_parallel_workers_per_gather TO 0, o plano resultante será mais fácil de entender. Geralmente, essa é a primeira coisa que faço ao analisar o desempenho de uma consulta, a menos que a paralelização seja exatamente o que estou tentando estudar. Quaisquer melhorias que eu faça serão em seguida, geralmente traduz de volta para execução paralela.)

    Um bitmap está inerentemente em ordem física. Classificá-lo não é uma etapa separada de apenas criá-lo. O PostgreSQL lê os blocos nessa ordem, um por um. Cabe ao sistema operacional/sistema de arquivos aglutinar essas leituras individuais em leituras sequenciais, se assim decidir. Na minha experiência, você precisa ler quase todos os blocos antes que isso tenha um bom efeito. Se você ler apenas a cada quinto bloco (estocásticamente), também poderá fazer leituras aleatórias. Não posso dizer pelos seus dados que fração da tabela 28755 blocos representa.

    Agora, por que um bitmap criado durante a fase de varredura de índice de bitmap tem tantas chaves? Existe um índice ro__status que pode indicar que existem apenas cerca de 200 registros com status 70 e 73

    Índices no PostgreSQL não contêm inerentemente nenhuma informação de visibilidade. "ro__status" não pode saber quais desses ctid ainda estão visíveis, então todos eles precisam ser inseridos no bitmap. Em seguida, a maioria deles é rejeitada no estágio de varredura de heap como sendo invisível. (Isso não é relatado explicitamente, como são as rejeições de verificação e filtro. Você deve inferir pela diferença entre o tamanho do bitmap e a contagem final de linhas. No caso de BitmapAnd e BitmapOr, você não pode fazer isso facilmente, pois o tamanho do bitmap não é preciso).

    Então esse é o cerne do problema, você está visitando mais de 50.000 tuplas apenas para encontrar 195 vivas. Limpar essas tuplas mortas do índice é uma das principais tarefas da aspiração. Portanto, é provável que sua mesa não esteja sendo aspirada o suficiente. Você pode testar isso de forma bem simples, limpar a mesa e ver se isso resolve o problema. Se isso não acontecer, então você provavelmente tem instantâneos de longa data que estão impedindo que o vácuo seja eficaz, então vá caçá-los.

    Os índices Btree têm um recurso de "microvácuo" onde uma varredura de índice regular mata uma tupla de índice que descobriu apontar para uma tupla de heap morta para todos. Mas as varreduras de índice de bitmap não implementam isso, pois não revisitam o índice após a consulta inicial, portanto, não há uma boa oportunidade para eliminar a tupla do índice. As varreduras de bitmap se beneficiarão desse microvácuo, mas não realizarão o microvácuo por si mesmas. Isso pode levar a uma situação perversa em que quanto mais varreduras de bitmap são preferidas em relação a varreduras de índice regulares, mais inchada a parte relevante do índice se torna até que as varreduras de bitmap comecem a ter um desempenho pior. O aumento da aspiração pode corrigir isso, mas se você não quiser aumentá-lo ainda mais, poderá apenas desencorajar os bitmaps em geral.

    • 5

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve