Postgres newbie here.
Je me demande si cette requête est optimisée ou non? J'ai essayé de JOIN ON uniquement les valeurs qui sont 100% nécessaires et en laissant toutes les conditions dynamiques dans la clause WHERE. Voir ci-dessous.
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;
Remarque: Pour le contexte, ce proc vérifie si un utilisateur est également un employé (privilèges élevés / type d'utilisateur différent).
Quoi qu'il en soit, est-ce la bonne façon de procéder? Le JOIN ON doit-il contenir plus d'instructions comme la vérification de expired_at IS NULL, par exemple? Pourquoi ou pourquoi cela n'a-t-il pas de sens?
SELECT version();
)Réponses:
Logiquement , cela ne fait aucune différence que vous placiez des conditions dans la clause join d'un
INNER JOIN
ou dans la mêmeWHERE
clauseSELECT
. L'effet est le même.(Pas le cas pour
OUTER JOIN
!)Tout en fonctionnant avec les paramètres par défaut, cela ne fait aucune différence pour le plan de requête ou les performances . Postgres est libre de réarranger et rejoint
JOIN
etWHERE
conditions dans sa quête pour le meilleur plan de requête - tant que le nombre de tables est pas supérieure à lajoin_collapse_limit
(par défaut8
). Détails:Pour la lisibilité et la maintenabilité, il est logique de placer des conditions qui relient les tables dans la
JOIN
clause respective et les conditions générales dans laWHERE
clause.Votre requête semble très bien. J'utiliserais des alias de table pour réduire le bruit, cependant.
Détail mineur:
int2 '1'
ou même1::int2
sont plus sensibles que(1)::INT2
. Et tout en se comparant à une valeur de type de données numérique bien défini, une constante numérique simple1
est également suffisante.la source
Quelques points ..
Si vous vous joignez à une condition du même nom (
user_id
) dans votre cas, vous pouvez utiliserUSING (user_id)
plutôt queON (a.user_id = b.user_id)
. Cela évite également qu'une colonne redondante ne soit potentiellement sortie (si vous exécutezSELECT *
en production).1::int2
est problématique. Soitstatus
, etis_primary
et d'autres sont déjàint2
dans ce cas, le littéral 1 sera automatiquement casté en int2, ou int2 casté en int comme pg le juge approprié. Ou, si vous les stockez en tant qu'ints réguliers et que vous les jetez comme si cela faisait une différence dans le calcul - ce qui n'est pas le cas, le casting seul en fait une proposition perdante.Lorsque cela est possible, tous les :: int2 devraient probablement être stockés en tant que
boolean
. Ensuite, vous pouvez également écrire votreWHERE
condition pour être plus simple.Pour votre type et votre statut, vous souhaiterez peut-être un
ENUM
type.la source