Abfrage integrieren
Indem Sie die Logik an mehreren Stellen verbessern, können Sie die gesamte Operation in eine einzige Abfrage integrieren. Das Umschließen in eine SQL-Funktion ist optional:
CREATE OR REPLACE FUNCTION f_elems(_action_id integer)
RETURNS SETOF integer AS
$func$
WITH RECURSIVE l AS (
SELECT a.category_id, l.local_id
FROM action a
JOIN local l USING (local_id)
WHERE a.action_id = $1
UNION ALL
SELECT l.category_id, c.local_id
FROM l
JOIN local c ON c.parent_id = l.local_id -- c for "child"
)
SELECT e.element_id
FROM l
JOIN element e USING (category_id, local_id);
$func$ LANGUAGE sql STABLE;
Ruft alle element_id
ab für gleiche und untergeordnete Lokale einer gegebenen action_id
.
Aufruf:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
db<>fiddle hier
ALTER sqlfiddle
Dies sollte wesentlich sein schon aus mehreren Gründen schneller. Die offensichtlichsten sind:
- Ersetzen Sie reines SQL durch langsame Schleifen in plpgsql.
- Einschränken Sie den Anfangssatz der rekursiven Abfrage ein.
- Entfernen Sie unnötiges und notorisch langsames
IN
konstruieren.
Ich rufe mit SELECT * FROM ...
an statt nur SELECT
, obwohl die Zeile nur eine einzige Spalte hat, um den Spaltennamen von OUT
zu erhalten Parameter (element_id
) habe ich im Funktionsheader deklariert.
Noch schneller
Indizes
Ein Index auf action.action_id
wird durch den Primärschlüssel bereitgestellt.
Aber Sie haben vielleicht den Index auf local.parent_id
übersehen . Wenn Sie schon dabei sind, machen Sie daraus einen übergreifenden mehrspaltigen Index (Postgres 9.2+) mit parent_id
als erstes Element und local_id
als zweite. Dies sollte sehr hilfreich sein, wenn die Tabelle local
ist groß. Wenig oder gar nicht für einen kleinen Tisch:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
Wieso den? Siehe:
Schließlich ein mehrspaltiger Index
auf Tabelle element
sollte weiter helfen:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
Die dritte Spalte element_id
ist nur sinnvoll, um daraus einen deckenden Index zu machen . Wenn Ihre Abfrage mehr Spalten aus der Tabelle element
abruft , möchten Sie vielleicht weitere Spalten zum Index hinzufügen oder element_id
weglassen . Beides macht es schneller.
Materialisierte Ansicht
Wenn Ihre Tabellen erhalten nur wenige oder keine Aktualisierungen, eine materialisierte Ansicht, die den vorberechneten Satz aller Paare (action_id, element_id)
bereitstellt das Teilen derselben Kategorie würde dies blitzschnell machen . Machen Sie (action_id, element_id)
(in dieser Reihenfolge) den Primärschlüssel.