PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Dołącz do dwóch tabel używając id i potomków z drzewa jak tabela

Zintegruj zapytanie

Udoskonalając logikę w kilku miejscach, możesz zintegrować całą operację w jednym zapytaniu. Zawijanie w funkcję SQL jest opcjonalne:

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;

Pobiera wszystkie element_id dla tego samego i podrzędnego lokalnego dla danego action_id .

Zadzwoń:

SELECT * FROM f_elem(3);

element_id
-----------
6
7

db<>fiddle tutaj
STARY sqlfiddle

Powinno to być zasadniczo szybciej już z kilku powodów. Najbardziej oczywiste to:

  • Zastąp czystym SQL wolnym zapętleniem w plpgsql.
  • Zawęź początkowy zestaw zapytania rekurencyjnego.
  • Usuń niepotrzebne i notorycznie wolne IN konstruować.

Dzwonię z SELECT * FROM ... zamiast po prostu SELECT , nawet jeśli wiersz ma tylko jedną kolumnę, aby uzyskać nazwę kolumny OUT parametr (element_id ) Zadeklarowałem w nagłówku funkcji.

Szybciej, ale

Indeksy

Indeks na action.action_id jest dostarczany przez klucz podstawowy.

Ale mogłeś przegapić indeks local.parent_id . Będąc przy tym, postaraj się, aby pokrywał się wielokolumnowym indeksem (Postgres 9.2+) z parent_id jako pierwszy element i local_id jako drugi. Powinno to bardzo pomóc, jeśli tabela local jest duży. Nie tak bardzo lub wcale na mały stolik:

CREATE INDEX l_mult_idx ON local(parent_id, local_id);

Czemu? Zobacz:

Wreszcie indeks wielokolumnowy w tabeli element powinien pomóc trochę więcej:

CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);

Trzecia kolumna element_id przydaje się tylko, aby uczynić go indeksem obejmującym . Jeśli zapytanie pobierze więcej kolumn z tabeli element , możesz dodać więcej kolumn do indeksu lub usunąć element_id . Albo przyspieszy to.

Widok zmaterializowany

Jeśli Twoje tabele otrzymują niewiele aktualizacji lub nie otrzymują ich wcale, zmaterializowany widok dostarczający wstępnie obliczony zestaw wszystkich par (action_id, element_id) udostępnienie tej samej kategorii sprawiłoby, że to szybkie rozjaśnianie . Utwórz (action_id, element_id) (w tej kolejności) klucz podstawowy.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgres hstore istnieje i nie istnieje w tym samym czasie

  2. Jak przeszukiwać metadane indeksów w PostgreSQL

  3. Jak zwrócić tylko czas pracy z rezerwacji w PostgreSql?

  4. Zapytanie Ecto - daty + interwały Postgres + interpolacja zapytań

  5. SQLite do Postgres (Heroku) GROUP BY