65 votes

Un JOIN est-il plus rapide qu'un WHERE?

Supposons que j'ai deux tables qui sont liées (l'un a une clé étrangère vers les autres) :

CREATE TABLE Document (
  Id INT PRIMARY KEY,
  Name VARCHAR 255
)

CREATE TABLE DocumentStats (
  Id INT PRIMARY KEY,
  DocumentId INT, -- this is a foreign key to table Document
  NbViews INT
)

Je sais, ce n'est pas la façon la plus intelligente de faire les choses, mais c'est le meilleur exemple que je pouvais venir.

Maintenant, je veux obtenir tous les documents qui ont plus de 500 points de vue. Les deux solutions qui me viennent à l'esprit sont :

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

ou :

SELECT *
FROM Document
INNER JOIN DocumentStats
ON Document.Id = DocumentStats.Id
WHERE DocumentStats.NbViews > 500

Sont à la fois les requêtes équivalent, ou est-il une façon de faire qui est de loin meilleur que les autres ? Si oui, pourquoi ?

Je suis conscient que mon exemple n'est pas parfait, et que les requêtes peuvent avoir besoin de quelques réglages, mais j'espère que vous avez obtenu le point ;) !

EDIT: comme l'a demandé dans les réponses à cette question visait à MSSQL, mais je serais intéressé de savoir si il est différent pour d'autres moteurs de base de données (MySQL, etc...)

50voto

Mehrdad Afshari Points 204872

Théoriquement, non, cela ne devrait pas être plus rapide. L'optimiseur de requêtes doit pouvoir générer un plan d'exécution identique. Cependant, certains moteurs de base de données peuvent produire de meilleurs plans d'exécution pour l'un d'entre eux (cela ne devrait pas se produire pour une requête aussi simple, mais pour des requêtes suffisamment complexes). Vous devriez tester les deux et voir (sur votre moteur de base de données).

21voto

Mike J Points 1895

La Performance de "JOINDRE" ou "OÙ"... tout dépend de la façon dont le moteur de base de données est en mesure d'optimiser la requête pour vous. Il prendra en compte tous les indices que vous pourriez avoir sur les colonnes retournées et considérer que l'exécution des clauses where et JOIN aussi descendre à la physique du fichier de base de données elle-même et de son niveau de fragmentation et même la technologie de stockage que vous utilisez pour stocker les fichiers de base de données.

MSSql server exécute les requêtes dans l'ordre suivant (cela devrait vous donner une idée des fonctions de l'clauses where et JOIN)

Microsoft Sql Server query processus de commande

ce qui suit est tiré de l'excellente série de livres à propos de Microsoft SQL Server, Microsoft SQL Server 2005: T-SQL d'Interrogation qui peut être trouvé ici

(Étape 8), SÉLECTIONNEZ (Étape 9) DISTINCT (Étape 11)
(Étape 1) à PARTIR de *left_table*
(Étape 3) *join_type* ADHÉRER *right_table*
(Étape 2) *join_condition*
(Étape 4) OÙ *where_condition*
(Étape 5) GROUP BY *group_by_list*
(Étape 6) AVEC [CUBE|CUMULATIF]
(Étape 7) après AVOIR *having_clause*
(Étape 10) PAR *order_by_list*

13voto

Sam Saffron Points 56236

Il n'y a aucun moyen de répondre correctement à cette question sans se limiter à une base de données cible.

Pour MS-SQL, les deux requêtes donnent les mêmes plans d'exécution, mais gardez à l'esprit les points suivants:

 SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500
 

C'est vraiment risqué puisqu'il est facile d'oublier la condition de jointure dans la clause WHERE et de se retrouver avec une jointure croisée désagréable.

4voto

Greg Points 132247

Au moins dans MySQL, ils seront tous deux optimisés pour la même requête.

2voto

HLGEM Points 54641

Explicite les jointures sont plus faciles à entretenir que l'intention de la requête est beaucoup plus claire. Aussi, ils ne sont pas soumis à la croisée accidentelle rejoint donc si vous avez une jointure croisée dans la requête, le responsable sait qu'il était destiné à être là.

Si vous avez besoin d'utiliser les jointures externes, vous devez savoir que l' *= la syntaxe est obsolète dans SQL Server et sera bientôt supprimé. Aussi actuellement, il ne fonctionne pas comme prévu tout le temps et ne peut donner des résultats corrects et donc ne devraient JAMAIS être utilisés. Le mélange explicite les jointures externes et la clause where jointures (implicite jointures) effectue une requête beaucoup plus difficile pour un responsable de lire et de comprendre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X