sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo hacer que la consulta date_part llegue al índice?

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 a to_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. Usa datelocal < '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 usa date_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: