Se eu buscar apenas uma linha, a consulta demora muito mais: 1433 ms vs 23 ms
Existe um trabalho em torno?
Lento:
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM "modwork_ticket" WHERE
"modwork_ticket"."email_sender_id" = '[email protected]'
ORDER BY "modwork_ticket"."date_created" ASC limit 1;
--------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.43..542.14 rows=1 width=1146) (actual time=1433.128..1433.129 rows=1 loops=1)
Buffers: shared hit=1466151 read=4661
-> Index Scan using modwork_ticket_date_created on modwork_ticket (cost=0.43..606714.36 rows=1120 width=1146) (actual time=1433.125..1433
Filter: ((email_sender_id)::text = '[email protected]'::text)
Rows Removed by Filter: 1705251
Buffers: shared hit=1466151 read=4661
Planning time: 2.504 ms
Execution time: 1433.218 ms
Velozes:
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM "modwork_ticket" WHERE
"modwork_ticket"."email_sender_id" = '[email protected]'
ORDER BY "modwork_ticket"."date_created" ASC;
--------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=4335.83..4338.63 rows=1120 width=1146) (actual time=23.637..23.794 rows=584 loops=1)
Sort Key: date_created
Sort Method: quicksort Memory: 732kB
Buffers: shared hit=544 read=4
-> Bitmap Heap Scan on modwork_ticket (cost=25.11..4279.11 rows=1120 width=1146) (actual time=20.479..22.595 rows=584 loops=1)
Recheck Cond: ((email_sender_id)::text = '[email protected]'::text)
Heap Blocks: exact=538
Buffers: shared hit=541 read=4
-> Bitmap Index Scan on modwork_ticket_email_sender_id_like (cost=0.00..24.83 rows=1120 width=0) (actual time=20.388..20.388 rows=
Index Cond: ((email_sender_id)::text = '[email protected]'::text)
Buffers: shared hit=3 read=4
Planning time: 0.173 ms
Execution time: 23.974 ms
Versão:
PostgreSQL 9.6.3 on x86_64-suse-linux-gnu, compiled by gcc (SUSE Linux) 4.7.2 20130108 [gcc-4_7-branch revision 195012], 64-bit
Eu corro "VACUUM ANALYZE" antes de executar as consultas acima.
O problema é que as linhas para '[email protected]' são deficientes em valores com um date_created inicial, mas o planejador não sabe disso. Ele pensa que eles estão espalhados uniformemente, então ele encontrará um cedo ao caminhar
modwork_ticket_date_created
e poderá parar então. Mas, em vez disso, precisa percorrer 1.705.251 deles.Você pode criar um índice
(email_sender_id text_pattern_ops, date_created)
e ele poderá pular diretamente para a tupla desejada. Isso deve ser muito mais rápido do que qualquer um dos planos existentes. (Eu propus a inclusãotext_pattern_ops
puramente porque o nome do índice existente tem a palavra "like" nele, então suponho que já tenha sido definido dessa maneira - mas talvez você realmente tenha uma coluna chamada "like". Seria melhor se você nos mostra as definições para que não tenhamos que adivinhar coisas como esta). Esse índice pode substituir um existente, portanto, o número geral de índices pode permanecer o mesmo.Se você não deseja criar o índice e deseja apenas que ele use o 2º plano, pode forçá-lo escrevendo a consulta assim:
Ao adicionar algo à data antes de classificar, ele
PostgreSQL
faz pensar que não pode usar o índice de data.Assim que a v10
PostgreSQL
for lançada e você fizer upgrade para ela, você poderá criar uma definição de estatística avançada para a dependência funcional entre as duas colunas, o que também pode ser suficiente para fazer com que ela escolha o melhor plano.modwork_ticket_email_sender_id_like
índicemodwork_ticket_date_created
índicePortanto, ele acha que há menos trabalho para iniciar da linha mais antiga no índice ordenado até encontrar uma linha que tenha
((email_sender_id)::text = '[email protected]'::text)
do que coletar todas((email_sender_id)::text = '[email protected]'::text)
no índice e classificá-las para encontrar a mais antiga.Você pode tentar atualizar as estatísticas,
E, em seguida, tente executar novamente a consulta novamente. Se isso não funcionar, você pode querer aumentar as estatísticas em
(email_sender_id)::text
. E se isso não funcionar, você pode querer colar os dois índices para que possamos aconselhá-lo - ou considere mesclá-los (email_sender_id, date_created).