Integrar consulta
Mejorando la lógica en varios lugares, puede integrar toda la operación en una sola consulta. Envolver en una función SQL es 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 los element_id para los locales iguales y secundarios de un action_id determinado .
Llamar:
SELECT * FROM f_elem(3);
element_id
-----------
6
7
db<>fiddle aquí
ANTIGUO sqlfiddle
Esto debería ser sustancialmente más rápido ya por varias razones. Los más obvios son:
- Sustituya SQL puro por bucle lento en plpgsql.
- Restringir el conjunto inicial de la consulta recursiva.
- Eliminar
INinnecesario y notoriamente lento construir.
Estoy llamando con SELECT * FROM ... en lugar de simplemente SELECT , aunque la fila tiene solo una columna, para obtener el nombre de columna de OUT parámetro (element_id ) Declaré en el encabezado de la función.
Más rápido, aún
Índices
Un índice en action.action_id es proporcionada por la clave principal.
Pero es posible que te hayas perdido el índice en local.parent_id . Mientras lo hace, conviértalo en un índice de varias columnas de cobertura (Postgres 9.2+) con parent_id como primer elemento y local_id como segundo Esto debería ayudar mucho si la tabla local es grande. No tanto o nada para una mesa pequeña:
CREATE INDEX l_mult_idx ON local(parent_id, local_id);
¿Por qué? Ver:
Finalmente, un índice de varias columnas
en la tabla element debería ayudar un poco más:
CREATE INDEX e_mult_idx ON element (category_id, local_id, element_id);
La tercera columna element_id solo es útil para convertirlo en un índice de cobertura . Si su consulta recupera más columnas de la tabla element , es posible que desee agregar más columnas al índice o soltar element_id . Cualquiera de los dos lo hará más rápido.
Vista materializada
Si sus tablas reciben pocas o ninguna actualización, una vista materializada que proporciona el conjunto precalculado de todos los pares (action_id, element_id) compartir la misma categoría haría que esto fuera rápido como un rayo . Hacer (action_id, element_id) (en ese orden) la clave principal.