PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Свържете две таблици, като използвате id и потомци от дървоподобна таблица

Интегриране на заявка

Подобрявайки логиката на няколко места, можете да интегрирате цялата операция в една заявка. Обвиването в SQL функция не е задължително:

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;

Извлича всички element_id за същите и дъщерни локали на даден action_id .

Обаждане:

SELECT * FROM f_elem(3);

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

db<>fiddle тук
СТАРИ sqlfiddle

Това трябва да е значително вече по-бързо поради няколко причини. Най-очевидните от тях са:

  • Заместете чист SQL за бавен цикъл в plpgsql.
  • Ограничете началния набор от рекурсивната заявка.
  • Премахнете ненужното и известно бавно IN конструирам.

Обаждам се с SELECT * FROM ... вместо само SELECT , въпреки че редът има само една колона, за да получите името на колоната на OUT параметър (element_id ) Декларирах в заглавката на функцията.

По-бързо, но

Индекси

Индекс на action.action_id се предоставя от първичния ключ.

Но може да сте пропуснали индекса на local.parent_id . Докато го правите, направете го покриващ многоколонен индекс (Postgres 9.2+) с parent_id като първи елемент и local_id като втори. Това трябва да помогне много, ако таблицата local е голямо. Не толкова или изобщо не за малка маса:

CREATE INDEX l_mult_idx ON local(parent_id, local_id);

Защо? Вижте:

И накрая, индекс с няколко колони на таблица element трябва да помогне още:

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

Третата колона element_id е полезен само за превръщането му в покриващ индекс . Ако вашата заявка извлече повече колони от таблицата element , може да искате да добавите още колони към индекса или да премахнете element_id . И двете ще го направят по-бързо.

Материализиран изглед

Ако вашите таблици получават малко или никакви актуализации, материализиран изглед, предоставящ предварително изчислен набор от всички двойки (action_id, element_id) споделянето на същата категория би направило това светкавично бързо . Направете (action_id, element_id) (в този ред) първичния ключ.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как мога да направя по-малко от, по-голямо от в JSON полета на Postgres?

  2. JPA 2 @SequenceGenerator @GeneratedValue, генериращ уникално нарушение на ограничението

  3. Използване на UUID с EclipseLink и PostgreSQL

  4. Как да получите деня на годината от дата в PostgreSQL

  5. Postgres:трябва ли да се създават индекси преди или след попълване на таблици