Postgres novato aquí.
Me pregunto si esta consulta está optimizada o no. Intenté unirme solo a los valores que son 100% necesarios y dejar todas las condiciones dinámicas en la cláusula WHERE. Vea abajo.
SELECT *
FROM
myapp_employees
JOIN myapp_users ON
myapp_users.user_id=myapp_employees.user_id
JOIN myapp_contacts_assoc ON
myapp_contacts_assoc.user_id=myapp_users.user_id
JOIN myapp_contacts ON
myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
WHERE
myapp_contacts.value='[email protected]' AND
myapp_contacts.type=(1)::INT2 AND
myapp_contacts.is_primary=(1)::INT2 AND
myapp_contacts.expired_at IS NULL AND
myapp_employees.status=(1)::INT2 AND
myapp_users.status=(1)::INT2
LIMIT 1;
Nota: Para el contexto, este proceso está verificando si un usuario también es un empleado (privilegios elevados / tipo de usuario diferente).
De todos modos, ¿es este el camino correcto? ¿Debería JOIN ON contener más sentencias como, por ejemplo, comprobar expired_at IS NULL? ¿Por qué o por qué esto no tiene sentido?
SELECT version();
)Respuestas:
Lógicamente , no hace ninguna diferencia si coloca condiciones en la cláusula de unión de una
INNER JOIN
o en laWHERE
cláusula de la mismaSELECT
. El efecto es el mismo.(¡No es el caso
OUTER JOIN
!)Mientras opera con la configuración predeterminada, tampoco hay diferencia para el plan de consulta o el rendimiento . Postgres es libre para reorganizar y se une
JOIN
yWHERE
condiciones en su búsqueda de la mejor plan de consulta - siempre y cuando el número de tablas no es mayor que eljoin_collapse_limit
(por defecto8
). Detalles:Para facilitar la lectura y la mantenibilidad , tiene sentido colocar condiciones que conecten tablas en la
JOIN
cláusula respectiva y condiciones generales en laWHERE
cláusula.Su consulta se ve bien. Sin embargo, usaría alias de tabla para reducir el ruido.
Detalle menor:
int2 '1'
o incluso1::int2
son más sensibles que(1)::INT2
. Y mientras se compara con un valor de tipo de datos numéricos bien definido, una constante numérica simple también1
es suficiente.fuente
Un par de puntos ...
Si se une a una condición con el mismo nombre (
user_id
) en su caso, puede usar enUSING (user_id)
lugar deON (a.user_id = b.user_id)
. Esto también evita que una columna redundante se emita potencialmente (si estáSELECT *
en producción).1::int2
es problemático O bienstatus
, yis_primary
otros ya estánint2
en cuyo caso el literal 1 se convertirá automáticamente en int2, o int2 se convertirá en int como pg lo crea conveniente. O bien, si los almacena como entradas regulares y los rechaza como si eso hiciera una diferencia en el cálculo, lo que no es así, solo el elenco lo convierte en una propuesta perdedora.Cuando sea posible, todos los :: int2 probablemente deberían almacenarse como
boolean
. Entonces puedes escribir tuWHERE
condición para que sea más simple también.Para su tipo y estado, es posible que desee un
ENUM
tipo.fuente