PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come ottenere la query date_part per raggiungere l'indice?

Bene, entrambe le tue query si trovano su tabelle diverse (reportimpression rispetto a reportimpressionday ), quindi il confronto delle due query in realtà non è un confronto. Hai ANALYZE Entrambi? Anche varie statistiche di colonna possono svolgere un ruolo. L'indice o il rigonfiamento della tabella potrebbero essere diversi. La maggior parte di tutte le righe si qualifica per febbraio 2019? ecc.

Un colpo al buio, confronta le percentuali di entrambi i tavoli:

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;

È quello per reportimpression più grande? Quindi potrebbe semplicemente superare il numero per il quale ci si aspetta che un indice possa aiutare.

In genere, il tuo indice reportimpression_datelocal_index on (datelocal) sembra buono e reportimpression_viewership_index consente anche scansioni solo indice se l'autovacuum supera il carico di scrittura sul tavolo. (Anche se impressions &agegroup sono solo merci morte per questo e funzionerebbe ancora meglio senza).

Risposta

Hai il 26.6 percent, and day is 26.4 percent per la mia domanda. Per una percentuale così elevata, gli indici in genere non sono per niente utili . Una scansione sequenziale è in genere il modo più veloce. Solo le scansioni solo indice possono ha ancora senso se la tabella sottostante è molto più grande. (Oppure hai grave table bloat e indici meno gonfi, il che rende gli indici di nuovo più attraenti.)

La tua prima domanda potrebbe essere appena oltre il punto di svolta. Prova a restringere l'intervallo di tempo finché non vedi scansioni solo indice. Non vedrai scansioni di indici (bitmap) con più del 5% circa di tutte le righe qualificate (dipende da molti fattori).

Query

Comunque sia, considera queste query modificate:

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;

Punti principali

  • Quando si utilizza il formato data localizzato come '2-1-2019' , passa a to_timestamp() con specificatori di formato espliciti. Altrimenti dipende dalle impostazioni locali e potrebbe interrompersi (silenziosamente) quando viene chiamato da una sessione con impostazioni diverse. Piuttosto, usa i formati di data / ora ISO come dimostrato che non dipendono dalle impostazioni locali.

  • Sembra che tu voglia includere l'intero mese di febbraio. Ma la tua domanda perde il limite superiore. Per uno, febbraio potrebbe avere 29 giorni. Un datelocal < '2-28-2019' esclude anche tutto il 28 febbraio. Usa datelocal < '2019-03-01' invece.

  • È più economico raggruppare e ordinare in base alla stessa espressione come hai fatto in SELECT elenca se puoi. Quindi usa date_trunc() Lì anche. Non usare espressioni diverse senza bisogno. Se hai necessità il datepart nel risultato, applicalo all'espressione raggruppata, come:

    SELECT date_part('day', date_trunc('day', datelocal)) AS day
    ...
    GROUP  BY date_trunc('day', datelocal)
    ORDER  BY date_trunc('day', datelocal);
    

    Codice un po' più rumoroso, ma più veloce (e forse anche più facile da ottimizzare per il pianificatore di query).

  • Utilizza l'aggregato FILTER clausola in Postgres 9.4 o successivo. È più pulito e un po' più veloce. Vedi: