Zoekopdracht integreren
Door de logica op meerdere plaatsen te verbeteren, kunt u de hele operatie in één query integreren. Inpakken in een SQL-functie is optioneel:
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;
Haalt alle element_id
. op voor dezelfde en onderliggende lokale bewoners van een gegeven action_id
.
Bel:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
db<>fiddle hier
OUDE sqlfiddle
Dit zou aanzienlijk . moeten zijn om verschillende redenen al sneller. De meest voor de hand liggende zijn:
- Vervang pure SQL voor langzame looping in plpgsql.
- Beperk de startset van de recursieve zoekopdracht.
- Verwijder onnodige en notoir trage
IN
construeren.
Ik bel met SELECT * FROM ...
in plaats van alleen SELECT
, ook al heeft de rij maar één kolom, om de kolomnaam van de OUT
. te krijgen parameter (element_id
) Ik heb aangegeven in de functiekop.
Sneller, maar toch
Indices
Een index op action.action_id
wordt geleverd door de primaire sleutel.
Maar misschien heb je de index op local.parent_id
gemist . Terwijl je toch bezig bent, maak er dan een bedekkende index met meerdere kolommen van (Postgres 9.2+) met parent_id
als eerste element en local_id
als tweede. Dit zou veel moeten helpen als de tabel local
is groot. Niet zo veel of helemaal niet voor een kleine tafel:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
Waarom? Zie:
Eindelijk een multi-column index
op tafel element
zou wat meer moeten helpen:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
De derde kolom element_id
is alleen nuttig om er een dekkende index van te maken . Als uw zoekopdracht meer kolommen ophaalt uit tabel element
, wilt u misschien meer kolommen aan de index toevoegen of element_id
. weglaten . Beide zullen het sneller maken.
Gematerialiseerde weergave
Als uw tabellen ontvangen weinig of geen updates, een gematerialiseerde weergave die de vooraf berekende set van alle paren biedt (action_id, element_id)
het delen van dezelfde categorie zou dit bliksemsnel maken . Maak (action_id, element_id)
(in die volgorde) de primaire sleutel.