Integrer forespørgsel
Forbedring af logikken flere steder, kan du integrere hele operationen i en enkelt forespørgsel. Indpakning i en SQL-funktion er valgfrit:
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;
Henter alle element_id
for samme og underordnede lokale af en given action_id
.
Ring til:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
db<>fiddle her
GAMMEL sqlfiddle
Dette bør være væsentligt hurtigere allerede af flere årsager. De mest oplagte er:
- Erstat ren SQL med langsom looping i plpgsql.
- Begræns startsættet for den rekursive forespørgsel.
- Fjern unødvendige og notorisk langsom
IN
konstruere.
Jeg ringer med SELECT * FROM ...
i stedet for blot SELECT
, selvom rækken kun har en enkelt kolonne, for at få kolonnenavnet på OUT
parameter (element_id
) Jeg erklærede i funktionshovedet.
Hurtigere, dog
Indeks
Et indeks på action.action_id
leveres af den primære nøgle.
Men du er muligvis gået glip af indekset på local.parent_id
. Mens du er i gang, skal du gøre det til et dækkende indeks med flere kolonner (Postgres 9.2+) med parent_id
som første element og local_id
som anden. Dette burde hjælpe meget, hvis tabellen local
er stor. Ikke så meget eller slet ikke for et lille bord:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
Hvorfor? Se:
Endelig et multi-kolonne indeks
på tabel element
burde hjælpe noget mere:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
Den tredje kolonne element_id
er kun nyttig for at gøre det til et dækkende indeks . Hvis din forespørgsel henter flere kolonner fra tabel element
, vil du måske tilføje flere kolonner til indekset eller droppe element_id
. Begge vil gøre det hurtigere.
Materialiseret visning
Hvis dine tabeller modtager få eller ingen opdateringer, en materialiseret visning, der giver det forudberegnede sæt af alle par (action_id, element_id)
at dele den samme kategori ville gøre dette lynhurtigt . Lav (action_id, element_id)
(i nævnte rækkefølge) den primære nøgle.