PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Optimierung von GROUP BY + COUNT DISTINCT für nicht verschachtelte jsonb-Spalte

Angenommen id nicht nur UNIQUE - wie durch Ihren UNIQUE INDEX erzwungen - aber auch NOT NULL . (Das fehlt in Ihrer Tabellendefinition.)

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;

Kürzeres Äquivalent:

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

Der LEFT [OUTER] JOIN war Rauschen, weil der folgende Test WHERE meta_split.value IS NOT NULL ist erzwingt einen INNER JOIN ohnehin. Verwendung von CROSS JOIN stattdessen.

Auch seit jsonb erlaubt sowieso keine doppelten Schlüssel auf der gleichen Ebene (d.h. die gleiche id kann nur einmal erscheinen pro (key, value) ), DISTINCT ist nur teurer Lärm. count(v.id) macht das gleiche billiger. Und count(*) ist äquivalent und billiger, aber - unter der Annahme von id ist NOT NULL wie oben angegeben.

count(*) hat eine separate Implementierung und ist etwas schneller als count(<value>) . Es unterscheidet sich leicht von count(v.*) . Es zählt alle Zeilen, egal was passiert. Während die andere Form NULL nicht zählt Werte.

Das heißt, solange id darf nicht NULL sein - wie oben angegeben. id sollte eigentlich der PRIMARY KEY sein , die intern sowieso mit einem eindeutigen B-Tree-Index implementiert ist, und alle Spalten - nur id hier - sind NOT NULL implizit. Oder zumindest NOT NULL . Ein UNIQUE INDEX nicht vollständig als Ersatz qualifiziert, es erlaubt immer noch NULL Werte, die nicht als gleich angesehen werden und mehrfach zulässig sind. Siehe:

Abgesehen davon nützen Indizes hier nichts, da sowieso alle Zeilen gelesen werden müssen. Das wird also nie ganz billig. Aber 62.000 Zeilen ist keineswegs eine lähmende Zeilenanzahl - es sei denn, Sie haben eine große Anzahl von Schlüsseln im jsonb Spalte.

Die verbleibenden Optionen zur Beschleunigung:

  1. Normalisieren Sie Ihr Design. Das Entschachteln von JSON-Dokumenten ist nicht kostenlos.

  2. Behalten Sie eine materialisierte Ansicht bei. Machbarkeit und Kosten hängen stark von Ihren Schreibmustern ab.

Da spielen vielleicht wieder Indizes eine Rolle ...