Eu tenho uma consulta SQL muito simples:
SELECT COUNT(DISTINCT x) FROM table;
Minha tabela possui cerca de 1,5 milhão de linhas. Esta consulta está sendo executada bem devagar; leva cerca de 7,5s, em comparação com
SELECT COUNT(x) FROM table;
o que leva cerca de 435ms. Existe alguma maneira de alterar minha consulta para melhorar o desempenho? Tentei agrupar e fazer uma contagem regular, além de colocar um índice em x; ambos têm o mesmo tempo de execução 7.5s.
performance
postgresql
count
distinct
ferson2020
fonte
fonte
\d
saídapsql
é boa) e especifique a coluna com a qual você está com problemas. Seria bom ver asEXPLAIN ANALYZE
duas consultas.Respostas:
Você pode usar isto:
Isso é muito mais rápido que:
fonte
COUNT(DISTINCT())
realiza a classificação, será definitivamente útil ter um índicecolumn_name
especialmente com uma quantidade relativamente pequena dework_mem
(onde o hash produzirá uma quantidade relativamente grande de lotes). Desde que, nem sempre é ruim de usar COUNT (DISTINCT () _, não é?Count(column)
conta apenas valores não nulos.count(*)
conta linhas. Portanto, a primeira / mais longa também contará a linha nula (uma vez). Altere paracount(column_name)
fazê-los se comportar da mesma maneira.Resultados:
O mesmo plano do CTE provavelmente também poderia ser produzido por outros métodos (funções da janela)
fonte
Se o seu
count(distinct(x))
for significativamente mais lento do que emcount(x)
seguida, você poderá acelerar essa consulta mantendo as contagens de valores x em uma tabela diferente, por exemplotable_name_x_counts (x integer not null, x_count int not null)
, usando gatilhos. Mas seu desempenho de gravação sofrerá e, se você atualizar váriosx
valores em uma única transação, precisará fazer isso em alguma ordem explícita para evitar um possível impasse.fonte
Eu também estava procurando a mesma resposta, porque em algum momento eu precisava total_count com valores distintos, juntamente com limite / deslocamento .
Porque é um pouco complicado de fazer - Obter uma contagem total com valores distintos, além de limite / deslocamento. Geralmente é difícil obter a contagem total com limite / deslocamento. Finalmente consegui o que fazer -
SELECT DISTINCT COUNT(*) OVER() as total_count, * FROM table_name limit 2 offset 0;
O desempenho da consulta também é alto.
fonte