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

Optimalizace GROUP BY + COUNT DISTINCT na nevnořeném sloupci jsonb

Za předpokladu id nejen UNIQUE - jak je vynuceno vaším UNIQUE INDEX - ale také NOT NULL . (To v definici tabulky chybí.)

SELECT meta_split.key, meta_split.value, count(*)
FROM   voc_cc348779bdc84f8aab483f662a798a6a v
CROSS  JOIN LATERAL jsonb_each(v.meta) AS meta_split
GROUP  BY meta_split.key, meta_split.value;

Kratší ekvivalent:

SELECT meta_split.key, meta_split.value, count(*)
FROM   voc_cc348779bdc84f8aab483f662a798a6a v, jsonb_each(v.meta) AS meta_split
GROUP  BY 1, 2;

LEFT [OUTER] JOIN byl šum, protože následující test WHERE meta_split.value IS NOT NULL vynutí INNER JOIN tak jako tak. Pomocí CROSS JOIN místo toho.

Také, protože jsonb stejně nepovoluje duplicitní klíče na stejné úrovni (což znamená stejné id se může zobrazit pouze jednou za (key, value) ), DISTINCT je jen drahý hluk. count(v.id) dělá totéž levněji. A count(*) je ekvivalentní a levnější, přesto - za předpokladu id je NOT NULL jak je uvedeno nahoře.

count(*) má samostatnou implementaci a je o něco rychlejší než count(<value>) . Je to nepatrně odlišné od count(v.*) . Počítá všechny řádky, ať se děje cokoliv. Zatímco druhá forma nepočítá NULL hodnoty.

Tedy pokud id nemůže být NULL - jak je uvedeno nahoře. id by měl být skutečně PRIMARY KEY , který je každopádně interně implementován s jedinečným indexem B-stromu, a všechny sloupce - jen id zde - NOT NULL implicitně. Nebo alespoň NOT NULL . UNIQUE INDEX není plně kvalifikováno jako náhrada, stále umožňuje NULL hodnoty, které nejsou považovány za stejné a jsou povoleny vícekrát. Viz:

Kromě toho jsou zde indexy k ničemu, protože se stejně musí číst všechny řádky. Takže tohle nikdy nebude moc levné. Ale 62 tisíc řádků není v žádném případě ochromující počet řádků – pokud nemáte velké množství klíčů v jsonb sloupec.

Zbývající možnosti pro urychlení:

  1. Normalizujte svůj design. Rozpojení dokumentů JSON není bezplatné.

  2. Udržujte si materializovaný pohled. Proveditelnost a náklady silně závisí na vašich vzorech zápisu.

V tom mohou opět hrát roli indexy ...




  1. VYBERTE řádky MySQL, kde je dnešní datum mezi dvěma sloupci DATE

  2. Jak odstraníte znak ze sloupce na serveru SQL?

  3. Blokovat SELECT, dokud nebudou k dispozici výsledky

  4. Jak získat data BLOB pomocí oracle ODBC