sql >> Database >  >> RDS >> PostgreSQL

Voeg twee tabellen samen met id en afstammelingen van een boomachtige tabel

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.




  1. Mysql join vanuit meerdere tabellen

  2. Oracle - bindvariabele gebruiken in LIKE-clausule van dynamische cursor

  3. geïnternationaliseerde reguliere expressie in postgresql

  4. WinDeath op notifyDataSetChanged()