Integrera fråga
Genom att förbättra logiken på flera ställen kan du integrera hela operationen i en enda fråga. Att slå in i en SQL-funktion är valfritt:
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;
Hämtar alla element_id
för samma och underordnade lokalbefolkningen av en given action_id
.
Ring:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
Detta bör vara väsentligt snabbare redan av flera anledningar. De mest uppenbara är:
- Ersätt ren SQL för långsam looping i plpgsql.
- Begränsa startuppsättningen för den rekursiva frågan.
- Ta bort onödiga och notoriskt långsamma
IN
konstruera.
Jag ringer med SELECT * FROM ...
istället för bara SELECT
, även om raden bara har en enda kolumn, för att få kolumnnamnet för OUT
parameter (element_id
) Jag deklarerade i funktionshuvudet.
Snabbare men ändå
Indeks
Ett index på action.action_id
tillhandahålls av primärnyckeln.
Men du kanske har missat indexet på local.parent_id
. Medan du håller på, gör det till ett täckande index med flera kolumner (Postgres 9.2+) med parent_id
som första element och local_id
som tvåa. Detta borde hjälpa mycket om tabellen local
är stor. Inte så mycket eller inte alls för ett litet bord:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
Varför? Se:
Slutligen ett flerkolumnindex
i tabellen element
borde hjälpa lite mer:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
Den tredje kolumnen element_id
är bara användbart för att göra det till ett täckande index . Om din fråga hämtar fler kolumner från tabellen element
, kanske du vill lägga till fler kolumner i indexet eller släppa element_id
. Båda kommer att göra det snabbare.
Materialiserad vy
Om dina tabeller får få eller inga uppdateringar, en materialiserad vy som ger den förberäknade uppsättningen av alla par (action_id, element_id)
att dela samma kategori skulle göra detta blixtsnabbt . Gör (action_id, element_id)
(i den ordningen) primärnyckeln.