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
INconstruir.
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.