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
IN
innecesario 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.