Tengo una consulta SQL muy simple:
SELECT COUNT(DISTINCT x) FROM table;
Mi mesa tiene aproximadamente 1.5 millones de filas. Esta consulta se ejecuta muy lentamente; toma alrededor de 7.5s, en comparación con
SELECT COUNT(x) FROM table;
que dura unos 435 ms. ¿Hay alguna forma de cambiar mi consulta para mejorar el rendimiento? He intentado agrupar y hacer un conteo regular, así como poner un índice en x; ambos tienen el mismo tiempo de ejecución de 7.5s.
performance
postgresql
count
distinct
ferson2020
fuente
fuente
\d
resultadopsql
es bueno) y especifique la columna con la que tiene problemas. Sería bueno verEXPLAIN ANALYZE
ambas consultas.Respuestas:
Puedes usar esto:
Esto es mucho más rápido que:
fuente
COUNT(DISTINCT())
realiza la clasificación, definitivamente será útil tener un índice encolumn_name
especial con una cantidad relativamente pequeña dework_mem
(donde el hash producirá cantidades relativamente grandes de lotes). Desde entonces, no siempre es malo usar COUNT (DISTINCT () _, ¿no?)Count(column)
solo cuenta valores no nulos.count(*)
cuenta filas. Entonces, el primero / más largo, también contará la fila nula (una vez). Cambie acount(column_name)
para que se comporten igual.Resultados:
El mismo plan que para el CTE probablemente también podría ser producido por otros métodos (funciones de ventana)
fuente
Si tu
count(distinct(x))
es significativamente más lento quecount(x)
entonces, puedes acelerar esta consulta manteniendo los conteos de valores x en una tabla diferente, por ejemplotable_name_x_counts (x integer not null, x_count int not null)
, usando disparadores. Pero su rendimiento de escritura se verá afectado y si actualiza variosx
valores en una sola transacción, deberá hacer esto en un orden explícito para evitar un posible punto muerto.fuente
También estaba buscando la misma respuesta, porque en algún momento necesitaba total_count con valores distintos junto con limit / offset .
Porque es un poco difícil de hacer: para obtener el recuento total con valores distintos junto con límite / desplazamiento. Por lo general, es difícil obtener el recuento total con límite / compensación. Finalmente conseguí la forma de hacerlo:
SELECT DISTINCT COUNT(*) OVER() as total_count, * FROM table_name limit 2 offset 0;
El rendimiento de las consultas también es alto.
fuente