sql >> Database teknologi >  >> RDS >> PostgreSQL

Optimering af GROUP BY + COUNT DISTINCT på ikke-indlejret jsonb-kolonne

Forudsat id ikke kun UNIQUE - som håndhævet af din UNIQUE INDEX - men også NOT NULL . (Det mangler i din tabeldefinition.)

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;

Kortere ækvivalent:

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 støj, fordi følgende test WHERE meta_split.value IS NOT NULL fremtvinger en INNER JOIN alligevel. Brug af CROSS JOIN i stedet.

Også da jsonb tillader ikke duplikerede nøgler på samme niveau alligevel (det betyder det samme id kan kun dukke op én gang pr. (key, value) ), DISTINCT er bare dyr støj. count(v.id) gør det samme billigere. Og count(*) er ækvivalent og billigere, men alligevel - forudsat id er NOT NULL som angivet øverst.

count(*) har en separat implementering og er lidt hurtigere end count(<value>) . Det er subtilt forskelligt fra count(v.*) . Det tæller alle rækker, uanset hvad. Mens den anden form ikke tæller NULL værdier.

Det vil sige, så længe id kan ikke være NULL - som der står øverst. id burde virkelig være den PRIMARY KEY , som alligevel er implementeret med et unikt B-træindeks internt, og alle kolonner - kun id her - er NOT NULL implicit. Eller i det mindste NOT NULL . Et UNIQUE INDEX ikke fuldt ud kvalificeres som erstatning, tillader den stadig NULL værdier, der ikke betragtes som ens og er tilladt flere gange. Se:

Ud over det er indekser til ingen nytte her, da alle rækker skal læses alligevel. Så det bliver aldrig særlig billigt. Men 62.000 rækker er på ingen måde et lammende rækkeantal - medmindre du har et stort antal nøgler i jsonb kolonne.

De resterende muligheder for at fremskynde det:

  1. Normaliser dit design. Det er ikke gratis at fjerne JSON-dokumenter.

  2. Oprethold et materialiseret syn. Gennemførlighed og omkostninger afhænger stærkt af dine skrivemønstre.

Det er her indekser kan spille en rolle igen ...




  1. Brug af Oracles GUID()-genererede ID'er i Grails/Hibernate

  2. Hvordan man øger en tæller og returnerer værdien i MySQL

  3. Hvordan gendanner man data fra en slettet Docker-container? Hvordan forbindes den til dataene igen?

  4. Hvad er MySQL VARCHAR max størrelsen?