Bueno, ambas consultas están en tablas diferentes (reportimpression
frente a reportimpressionday
), por lo que la comparación de las dos consultas realmente no es una comparación. ANALYZE
¿ambas cosas? Varias estadísticas de columna también pueden jugar un papel. El índice o la tabla pueden ser diferentes. ¿Califica una mayor parte de todas las filas para febrero de 2019? Etc.
Un tiro en la oscuridad, compare los porcentajes de ambas tablas:
SELECT tbl, round(share * 100 / total, 2) As percentage
FROM (
SELECT text 'reportimpression' AS tbl
, count(*)::numeric AS total
, count(*) FILTER (WHERE datelocal >= '2019-02-01' AND datelocal < '2019-03-01')::numeric AS share
FROM reportimpression
UNION ALL
SELECT 'reportimpressionday'
, count(*)
, count(*) FILTER (WHERE datelocal >= '2019-02-01' AND datelocal < '2019-03-01')
FROM reportimpressionday
) sub;
Es el de reportimpression
¿más grande? Entonces podría exceder el número para el que se espera que ayude un índice.
Generalmente, su índice reportimpression_datelocal_index
on (datelocal) se ve bien para él, y reportimpression_viewership_index
incluso permite escaneos de solo índice si el vacío automático supera la carga de escritura en la tabla. (Aunque impressions
&agegroup
son solo carga muerta para esto y funcionaría aún mejor sin él).
Respuesta
Obtuviste 26.6 percent, and day is 26.4 percent
para mi consulta Para un porcentaje tan grande, los índices normalmente no son útiles en absoluto . Una exploración secuencial suele ser la forma más rápida. Solo los escaneos de solo índice pueden todavía tiene sentido si la tabla subyacente es mucho más grande. (O usted tiene grave tabla hinchada e índices menos hinchados, lo que hace que los índices vuelvan a ser más atractivos).
Su primera consulta puede estar cruzando el punto de inflexión. Intente reducir el período de tiempo hasta que vea escaneos de solo índice. No verá escaneos de índice (mapa de bits) con más de aproximadamente el 5 % de todas las filas calificadas (depende de muchos factores).
Consultas
Sea como fuere, considera estas consultas modificadas:
SELECT date_part('hour', datelocal) AS hour
, SUM(views) FILTER (WHERE gender = 'male') AS male
, SUM(views) FILTER (WHERE gender = 'female') AS female
FROM reportimpression
WHERE datelocal >= '2019-02-01'
AND datelocal < '2019-03-01' -- '2019-02-28' -- ?
GROUP BY 1
ORDER BY 1;
SELECT date_trunc('day', datelocal) AS day
, SUM(views) FILTER (WHERE gender = 'male') AS male
, SUM(views) FILTER (WHERE gender = 'female') AS female
FROM reportimpressionday
WHERE datelocal >= '2019-02-01'
AND datelocal < '2019-03-01'
GROUP BY 1
ORDER BY 1;
Puntos principales
-
Cuando se usa un formato de fecha localizado como
'2-1-2019'
, vaya ato_timestamp()
con especificadores de formato explícitos. De lo contrario, esto depende de la configuración regional y podría romperse (silenciosamente) cuando se llama desde una sesión con una configuración diferente. En su lugar, utilice los formatos de fecha/hora ISO como se muestra, que no dependen de la configuración regional. -
Parece que quieres incluir el mes entero del mes de febrero. Pero su consulta pierde el límite superior. Por un lado, febrero puede tener 29 días. Un
datelocal < '2-28-2019'
excluye todo el 28 de febrero también. Usadatelocal < '2019-03-01'
en su lugar. -
Es más barato agrupar y ordenar por la misma expresión como tienes en el
SELECT
lista si puedes. Así que usadate_trunc()
ahí también. No uses diferentes expresiones sin necesidad. Si necesitas la parte de la fecha en el resultado, aplíquelo en la expresión agrupada, como:SELECT date_part('day', date_trunc('day', datelocal)) AS day ... GROUP BY date_trunc('day', datelocal) ORDER BY date_trunc('day', datelocal);
Código un poco más ruidoso, pero más rápido (y posiblemente también más fácil de optimizar para el planificador de consultas).
-
Use el agregado
FILTER
cláusula en Postgres 9.4 o posterior. Es más limpio y un poco más rápido. Ver: