PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como obter a consulta date_part para atingir o índice?


Bem, ambas as suas consultas estão em tabelas diferentes (reportimpression vs. reportimpressionday ), então a comparação das duas consultas realmente não é uma comparação. Você ANALISE Ambas? Várias estatísticas de coluna também podem desempenhar um papel. O inchaço do índice ou da tabela pode ser diferente. Uma parte maior de todas as linhas se qualifica para fevereiro de 2019? etc.

Um tiro no escuro, compare as porcentagens para ambas as tabelas:
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;

É aquele para reportimpression Maior? Em seguida, pode exceder o número para o qual se espera que um índice ajude.

Geralmente, seu índice reportimpression_datelocal_index on (datelocal) parece bom para ele, e reportimpression_viewership_index até permite varreduras somente de índice se o autovacuum superar a carga de gravação na mesa. (Embora impressões &grupo etário são apenas frete morto para isso e funcionaria ainda melhor sem).

Resposta


Você tem 26,6% e dia é 26,4% para minha consulta. Para uma porcentagem tão grande, os índices normalmente não são úteis de forma alguma . Uma varredura sequencial geralmente é a maneira mais rápida. Somente verificações somente de índice podem ainda faz sentido se a tabela subjacente for muito maior. (Ou você tem grave tabela inchada e índices menos inchados, o que torna os índices mais atraentes novamente.)

Sua primeira consulta pode ser apenas do outro lado do ponto de inflexão. Tente restringir o período de tempo até ver verificações somente de índice. Você não verá varreduras de índice (bitmap) com mais de 5% de todas as linhas qualificadas (dependendo de muitos fatores).

Consultas


Seja como for, considere 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;

Pontos principais


  • Ao usar o formato de data localizado como '2-1-2019' , acesse to_timestamp() com especificadores de formato explícitos. Caso contrário, isso depende das configurações de localidade e pode ser interrompido (silenciosamente) quando chamado de uma sessão com configurações diferentes. Em vez disso, use os formatos de data/hora ISO, conforme demonstrado, que não dependem das configurações de localidade.

  • Parece que você deseja incluir o mês inteiro de fevereiro. Mas sua consulta perde o limite superior. Por um lado, fevereiro pode ter 29 dias. Um datelocal <'2-28-2019' exclui todo o dia 28 de fevereiro também. Use datelocal <'2019-03-01' em vez de.

  • É mais barato agrupar e classificar pela mesma expressão como você tem no SELECT lista se puder. Então use date_trunc() ali também. Não use expressões diferentes sem necessidade. Se você precisar o datepart no resultado, aplique-o na expressão agrupada, como:
    SELECT date_part('day', date_trunc('day', datelocal)) AS day
    ...
    GROUP  BY date_trunc('day', datelocal)
    ORDER  BY date_trunc('day', datelocal);
    

    Um código um pouco mais barulhento, mas mais rápido (e possivelmente mais fácil de otimizar também para o planejador de consultas).

  • Use o agregado FILTER cláusula no Postgres 9.4 ou posterior. É mais limpo e um pouco mais rápido. Ver: