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.
- 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 (indicadasexact
naHeap Blocks
seção). Isso está correto? - Segundo, este mapa é passado para a fase Bitmap Heap Scan.
Recheck Cond
nã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? - O tamanho do bitmap refletido na
Heap Blocks: exact=28755
linha 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? - 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! - 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? - 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"