PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Junte duas tabelas usando id e descendentes da árvore como tabela

Integrar consulta


Melhorando a lógica em vários lugares, você pode integrar toda a operação em uma única consulta. Agrupar em uma função SQL é opcional:
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;

Recupera todos os element_id para mesmo local e local filho de um determinado action_id .

Ligar:
SELECT * FROM f_elem(3);

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

db<>fiddle aqui
ANTIGO sqlfiddle

Isso deve ser substancialmente mais rápido já por várias razões. As mais óbvias são:
  • Substitua o SQL puro por loop lento no plpgsql.
  • Restringir o conjunto inicial da consulta recursiva.
  • Remover desnecessário e notoriamente lento IN construir.

Estou ligando com SELECT * FROM ... em vez de apenas SELECT , mesmo que a linha tenha apenas uma coluna, para obter o nome da coluna do OUT parâmetro (element_id ) declarei no cabeçalho da função.

Mais rápido, ainda

Índices


Um índice em action.action_id é fornecido pela chave primária.

Mas você pode ter perdido o índice em local.parent_id . Enquanto isso, faça disso um índice de várias colunas (Postgres 9.2+) com parent_id como primeiro elemento e local_id como segundo. Isso deve ajudar muito se a tabela local é grande. Nem tanto ou nada para uma mesa pequena:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);

Por quê? Ver:

Por fim, um índice de várias colunas na tabela element deve ajudar um pouco mais:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);

A terceira coluna element_id só é útil para torná-lo um índice de cobertura . Se sua consulta recuperar mais colunas da tabela element , você pode querer adicionar mais colunas ao índice ou remover element_id . Qualquer um vai torná-lo mais rápido.

Visão materializada


Se suas tabelas recebem poucas ou nenhuma atualização, uma visão materializada fornecendo o conjunto pré-computado de todos os pares (action_id, element_id) compartilhar a mesma categoria tornaria isso muito rápido . Faça (action_id, element_id) (nessa ordem) a chave primária.