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
INkonstruieren.
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.