PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak uzyskać zapytanie date_part, aby trafić na indeks?

Cóż, oba zapytania znajdują się w różnych tabelach (reportimpression a reportimpressionday ), więc porównanie dwóch zapytań tak naprawdę nie jest porównaniem. Czy Analiza? Zarówno? Pewną rolę mogą również odgrywać różne statystyki kolumnowe. Indeks lub rozdęcie tabeli mogą być inne. Czy większa część wszystkich wierszy kwalifikuje się do lutego 2019? Itd.

Jedno ujęcie w ciemności, porównaj wartości procentowe dla obu tabel:

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;

To ten dla reportimpression większy? Wtedy może po prostu przekroczyć liczbę, dla której indeks ma pomóc.

Ogólnie rzecz biorąc, Twój indeks reportimpression_datelocal_index on (datelocal) wygląda na to dobrze, a reportimpression_viewership_index pozwala nawet na skanowanie tylko indeksu, jeśli autovacuum pokona obciążenie zapisu na stole. (Chociaż wyświetlenia &grupa wiekowa to tylko martwy ładunek za to i bez niego działałoby jeszcze lepiej).

Odpowiedź

Masz 26,6 procent, a dzień to 26,4 procent dla mojego zapytania. W przypadku tak dużego odsetka indeksy zazwyczaj nie są przydatne w ogóle . Skanowanie sekwencyjne jest zazwyczaj najszybszym sposobem. Tylko skanowanie tylko do indeksu może nadal ma sens, jeśli tabela bazowa jest znacznie większa. (Lub masz poważne rozdęcie tabeli i mniej rozdęte indeksy, co sprawia, że ​​indeksy znów są bardziej atrakcyjne.)

Twoje pierwsze zapytanie może dotyczyć właśnie punktu krytycznego. Spróbuj zawęzić przedział czasu, aż zobaczysz skany tylko z indeksem. Nie zobaczysz skanów indeksów (map bitowych), w których kwalifikuje się więcej niż około 5% wszystkich wierszy (w zależności od wielu czynników).

Zapytania

Tak czy inaczej, rozważ te zmodyfikowane zapytania:

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;

Główne punkty

  • W przypadku korzystania ze zlokalizowanego formatu daty jak '2-1-2019' , przejdź do to_timestamp() z jawnymi specyfikatorami formatu. W przeciwnym razie zależy to od ustawień regionalnych i może zostać przerwane (po cichu) po wywołaniu z sesji z innymi ustawieniami. Raczej używaj formatów daty / czasu ISO, jak pokazano, które nie zależą od ustawień regionalnych.

  • Wygląda na to, że chcesz uwzględnić cały miesiąc lutowy. Ale twoje zapytanie nie mieści się w górnej granicy. Po pierwsze, luty może mieć 29 dni. datelocal <'2-28-2019' wyklucza również wszystkie 28 lutego. Użyj datelocal <'2019-03-01' zamiast tego.

  • Taniej jest grupować i sortować według tego samego wyrażenia tak jak w SELECT spisuj, jeśli możesz. Użyj więc date_trunc() tam też. Nie używaj różnych wyrażeń bez potrzeby. Jeśli potrzebujesz część daty w wyniku, zastosuj ją do zgrupowanego wyrażenia, na przykład:

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

    Nieco bardziej hałaśliwy kod, ale szybszy (i prawdopodobnie łatwiejszy do optymalizacji również pod kątem planowania zapytań).

  • Użyj agregacji FILTR klauzula w Postgresie 9.4 lub nowszym. Jest czystszy i trochę szybszy. Zobacz:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Przechodź przez kolumny RECORD

  2. Scal ciągłe wiersze z Postgresql

  3. Jak zainstalować PostgreSQL 12 na Ubuntu 20.04 DigitalOcean?

  4. Jak używać Spring StandardPasswordEncode i Get Salt Generate?

  5. Jak to_char() działa w PostgreSQL