sql >> Databáze >  >> RDS >> PostgreSQL

Jak získat dotaz date_part na index hitů?

Oba vaše dotazy jsou v různých tabulkách (reportimpression vs. reportimpressionday ), takže srovnání těchto dvou dotazů opravdu není srovnání. ANALÝZA oba? Svou roli mohou hrát také různé statistiky sloupců. Index nebo tabulka nadýmání se mohou lišit. Má větší část všech řádků nárok na únor 2019? atd.

Jedna rána do tmy, porovnejte procenta pro obě tabulky:

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;

Je ten pro reportimpression větší? Pak může jen překročit číslo, pro které se očekává, že index pomůže.

Obecně platí, že váš index reportimpression_datelocal_index on (datelocal) vypadá dobře a reportimpression_viewership_index dokonce umožňuje skenování pouze s indexem, pokud autovakuum překonává zapisovací zátěž na stole. (Přestože zobrazení &věková skupina jsou pro to jen mrtvá nákladní doprava a bez nich by to fungovalo ještě lépe).

Odpověď

Máte 26,6 procenta a den je 26,4 procent pro můj dotaz. Pro tak velké procento nejsou indexy obvykle vůbec užitečné . Sekvenční skenování je obvykle nejrychlejší způsob. mohou pouze skenování pouze na základě indexu stále dává smysl, pokud je podkladová tabulka mnohem větší. (Nebo máte závažné tabulka nadýmání a méně nafouklé indexy, díky čemuž jsou indexy opět atraktivnější.)

Váš první dotaz může být právě přes bod zlomu. Zkuste zúžit časový rámec, dokud neuvidíte skenování pouze s indexem. Neuvidíte (bitmapové) skenování indexu s více než zhruba 5 % všech řádků, které splňují podmínky (závisí na mnoha faktorech).

Dotazy

Ať je to jak chce, zvažte tyto upravené dotazy:

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;

Hlavní body

  • Při použití lokalizovaného formátu data jako '2-1-2019' , přejděte přes to_timestamp() s explicitními specifikátory formátu. Jinak to závisí na nastavení národního prostředí a při volání z relace s jiným nastavením může dojít k přerušení (tiše). Používejte spíše formáty data a času ISO, jak je ukázáno, které nezávisí na nastavení národního prostředí.

  • Zdá se, že chcete zahrnout celý měsíc února. Ale váš dotaz mine horní hranici. Pro jednoho může mít únor 29 dní. datelocal <'2-28-2019' nezahrnuje také celý 28. únor. Použijte datelocal <'2019-03-01' místo toho.

  • Je levnější seskupovat a třídit podle stejného výrazu jako máte v SELECT seznam, pokud můžete. Použijte tedy date_trunc() tam taky. Nepoužívejte různé výrazy bez potřeby. Pokud potřebujete datepart ve výsledku, použijte jej na seskupený výraz, například:

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

    Trochu hlučnější kód, ale rychlejší (a možná snazší optimalizovat i pro plánovač dotazů).

  • Použijte souhrnný FILTR doložka v Postgres 9.4 nebo novější. Je čistší a o něco rychlejší. Viz:




  1. MySql - Jak získat hodnotu v předchozím řádku a hodnotu v následujícím řádku?

  2. Návrh databáze pro velmi velké množství dat

  3. Jak sprintf() chrání před SQL injection?

  4. jak vytvořit uloženou proceduru v oracle, která přijímá pole parametrů