sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo consultar de manera simple y eficiente las relaciones anidadas en SQL?

Como con cualquier consulta, el método más eficiente es "depende". Hay muchas variables en juego:el número de filas en las tablas, la longitud de las filas, si existen índices, la memoria RAM en el servidor, etc., etc.

La mejor manera que se me ocurre de manejar este tipo de problema (pensando en la mantenibilidad y un amplio enfoque de la eficiencia) es mediante el uso de CTE, lo que le permite crear un resultado temporal y reutilizar ese resultado a lo largo de su consulta. Las CTE usan la palabra clave CON y, esencialmente, alias un resultado como una tabla, para que pueda JOIN contra él varias veces:

WITH user_memberships AS (
    SELECT *
    FROM memberships
    WHERE user_id = ${id}
), user_apps AS (
    SELECT *
    FROM apps
    INNER JOIN user_memberships
        ON user_memberships.team_id = apps.team_id
), user_collections AS (
    SELECT *
    FROM collections
    INNER JOIN user_memberships
        ON user_memberships.team_id = collections.team_id
), user_webhooks AS (
    SELECT *
    FROM webhooks
    LEFT OUTER JOIN user_collections ON user_collections.id = webhooks.collection_id
    INNER JOIN user_memberships
        ON user_memberships.team_id = webhooks.team_id
        OR user_memberships.team_id = user_collections.team_id
)

SELECT events.* 
FROM events
WHERE app_id IN (SELECT id FROM user_apps)
OR collection_id IN (SELECT id FROM user_collections)
OR membership_id IN (SELECT id FROM user_memberships)
OR team_id IN (SELECT team_id FROM user_memberships)
OR user_id = ${id}
OR webhook_id IN (SELECT id FROM user_webhooks)
;

Los beneficios de hacerlo de esta manera son:

  1. Cada CTE puede aprovechar un índice en los predicados JOIN apropiados y devolver resultados solo para ese subconjunto más rápido, en lugar de que el planificador de ejecución intente resolver una serie de predicados complejos
  2. Los CTE se pueden mantener individualmente, lo que facilita la resolución de problemas con subconjuntos
  3. No estás violando el principio DRY
  4. Si el CTE tiene un valor fuera de la consulta, puede moverlo a un procedimiento almacenado y hacer referencia a ese en su lugar