sql >> Database >  >> RDS >> PostgreSQL

GROUP BY + COUNT DISTINCT optimaliseren voor niet-geneste jsonb-kolom

Uitgaande van id niet alleen UNIQUE - zoals afgedwongen door uw UNIQUE INDEX - maar ook NOT NULL . (Dat ontbreekt in uw tabeldefinitie.)

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;

Korter equivalent:

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

De LEFT [OUTER] JOIN was ruis omdat de volgende test WHERE meta_split.value IS NOT NULL forceert een INNER JOIN hoe dan ook. CROSS JOIN gebruiken in plaats daarvan.

Ook sinds jsonb staat sowieso geen dubbele sleutels toe op hetzelfde niveau (wat dezelfde id betekent) kan slechts één keer verschijnen per (key, value) ), DISTINCT is gewoon duur geluid. count(v.id) doet hetzelfde goedkoper. En count(*) is gelijkwaardig en goedkoper, maar toch - ervan uitgaande dat id is NOT NULL zoals bovenaan vermeld.

count(*) heeft een aparte implementatie en is iets sneller dan count(<value>) . Het is subtiel anders dan count(v.*) . Het telt alle rijen, wat er ook gebeurt. Terwijl de andere vorm niet meetelt NULL waarden.

Dat wil zeggen, zolang id kan niet NULL zijn - zoals bovenaan vermeld. id zou eigenlijk de PRIMARY KEY moeten zijn , die hoe dan ook intern is geïmplementeerd met een unieke B-tree-index, en alle kolommen - alleen id hier - zijn NOT NULL impliciet. Of in ieder geval NOT NULL . EEN UNIQUE INDEX kwalificeert niet volledig als vervanging, het laat nog steeds NULL toe waarden die niet als gelijk worden beschouwd en meerdere keren zijn toegestaan. Zie:

Afgezien daarvan hebben indexen hier geen zin, omdat alle rijen toch moeten worden gelezen. Dus heel goedkoop zal het nooit worden. Maar 62k rijen is op geen enkele manier een verlammend aantal rijen - tenzij je enorme aantallen sleutels hebt in de jsonb kolom.

De resterende opties om het te versnellen:

  1. Normaliseer je ontwerp. Het verwijderen van JSON-documenten is niet gratis.

  2. Zorg voor een gematerialiseerd beeld. Haalbaarheid en kosten zijn sterk afhankelijk van uw schrijfpatronen.

Dat is waar indexen weer een rol kunnen spelen ...




  1. Moet ik een GraphQL-ID als een tekenreeks op de client verwerken?

  2. MySQL-queryoptimalisatie van LIKE-term% ORDER BY int

  3. MariaDB:kan ik dubbele kolomnamen ophalen zonder 'AS' te gebruiken

  4. Een opgeslagen functieaanroep optimaliseren in SELECT- en WHERE-clausules