sql >> Databasteknik >  >> RDS >> PostgreSQL

Optimerar GROUP BY + COUNT DISTINCT på ohnestad jsonb-kolumn

Förutsatt id inte bara UNIQUE - enligt ditt UNIQUE INDEX - men också NOT NULL . (Det saknas i din tabelldefinition.)

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;

Kortare motsvarighet:

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 var brus eftersom följande test WHERE meta_split.value IS NOT NULL tvingar fram en INNER JOIN i alla fall. Använder CROSS JOIN istället.

Dessutom eftersom jsonb tillåter inte dubbletter av nycklar på samma nivå ändå (vilket betyder samma id kan bara dyka upp en gång per (key, value) ), DISTINCT är bara dyrt ljud. count(v.id) gör detsamma billigare. Och count(*) är likvärdig och billigare, men ändå - förutsatt id är NOT NULL som anges överst.

count(*) har en separat implementering och är något snabbare än count(<value>) . Det skiljer sig subtilt från count(v.*) . Den räknar alla rader, oavsett vad. Medan den andra formen inte räknas NULL värden.

Det vill säga så länge som id kan inte vara NULL - som det står överst. id borde verkligen vara PRIMARY KEY , som implementeras med ett unikt B-trädindex internt ändå, och alla kolumner - bara id här - är NOT NULL implicit. Eller åtminstone NOT NULL . Ett UNIQUE INDEX inte helt kvalificerar sig som ersättning, den tillåter fortfarande NULL värden som inte anses lika och som är tillåtna flera gånger. Se:

Bortsett från det är index till ingen nytta här, eftersom alla rader måste läsas ändå. Så det här kommer aldrig att bli särskilt billigt. Men 62 000 rader är inte ett förödande antal rader på något sätt - om du inte har ett stort antal nycklar i jsonb kolumn.

De återstående alternativen för att påskynda det:

  1. Normalisera din design. Att ta bort JSON-dokument är inte gratis.

  2. Behåll en materialiserad vy. Genomförbarhet och kostnader beror starkt på dina skrivmönster.

Det är där index kan spela en roll igen ...




  1. Lägg till en ny kolumn till en befintlig tabell i MySql med PHP med PDO

  2. Beräkna tidsskillnad i SQL med skift

  3. Division i Mysql-fråga

  4. Slumpmässigt vägt val i T-SQL