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řesto_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žijtedatelocal <'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 tedydate_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: