2010-12-17 6 views
1

J'ai trois façons de construire ma requête:Quelle requête sera la plus rapide?

Le premier:

select obj from table1 where condition1 and obj in (
select obj from table2 where condition2 and obj in (
select obj from table3 where condition3 and obj in (
... 
))) 

Le second:

select obj from table1 where condition1 
and obj in (select obj from table2 where condition2) 
and obj in (select obj from table3 where condition3) 
... 

Le troisième:

select table1.obj from table1 
inner join table2 on table2.obj = table1.obj and table2.condition='condition2' 
inner join table3 on table3.obj = table2.obj and table3.condition='condition3' 
... 
where table1.condition='condition1' 

Mes questions est si ces requêtes fournissent le même résultat et si ces requêtes sont également optimales.

Je suis assez sûr que les deux premières requêtes produisent la même sortie, mais la deuxième requête est plus rapide. Je ne suis pas sûr de la troisième requête.

AJOUTÉE

Il y a aussi une autre option:

select table1.obj from table1 
inner join table2 on table2.obj = table1.obj 
inner join table3 on table3.obj = table2.obj 
... 
where 
table1.condition='condition1' and 
table2.condition='condition2' and 
table3.condition='condition3' 
+0

Avez-vous essayé l'analyse comparative des 3? – scunliffe

Répondre

1

Bien qu'il y ait toujours des exceptions, l'option 3 est presque sûrement le meilleur/premier choix. En fonction de vos index et de vos distributions de données, le planificateur d'exécution des requêtes MySQL gérera l'ordre à extraire des tables.

Dans les autres cas, les sous-requêtes (Options 1 et 2) sont exécutées pour chaque ligne de la requête externe - elles peuvent être terriblement inefficaces. Ainsi, à la suite de l'instruction précédente, les sous-requêtes imbriquées (Option 1) peuvent être exponentiellement plus mauvaises que les sous-requêtes du premier ordre (Option 2) ou les jointures normales (Option 3).

Notez que pour INNER JOIN s, il n'a pas d'importance en ce qui concerne la performance ou fonctionnalité si les conditions supplémentaires sont dans les clauses JOIN ou dans les clauses WHERE. Par conséquent, votre autre option est effectivement équivalente à l'option 3.

0

Je soupçonne que la troisième requête serait le plus rapide. SQL est optimisé pour faire des JOINs une opération rapide.

Mais la seule façon de savoir avec vos données est de les essayer et de les voir.

1

La manière d'exécuter une requête est essentiellement la suivante: FROM (obtenir l'ensemble des données) => WHERE (appliquer des contraintes) => SELECT (afficher les résultats

La clause JOIN est toujours le meilleur choix pour joindre des données car dans la clause WHERE, seules les données correspondant aux clauses JOIN sont testées.

Dans le champ FROM, uniquement sur la clause ON sont sélectionnés et testés avant d'obtenir toutes les données pour le WHERE et le SELECT.

Dans vos deux premiers exemples, pour chaque SELECT, le contenu entier des tables est sélectionné pour les tests de la clause WHERE. C'est presque le même problème pour joindre la clause WHERE.

Les deux derniers exemples semblent être les mêmes.Je préférerais le dernier parce que l'utilisation de la clause ON dans le troisième exemple est utile pour RIGHT ou LEFT JOIN mais dans ce cas, cela ne fait qu'ajouter du désordre dans les clauses: FROM: obtenir la ressource précise, WHERE: appliquer les contraintes .

Cette explication est très schématique, mais je l'espère, il est logique ...

0

Eh bien, tout d'abord, ces requêtes ne renvoient pas nécessairement les mêmes résultats:

1. SELECT x FROM table1 WHERE x IN (SELECT x FROM table2 WHERE y = foo) 

2. SELECT x FROM table1 JOIN table 2 USING x WHERE table2.y = foo 

L'IN() supprime les doublons . Donc, si table2 contient 50 valeurs de x satisfaisant la condition y = foo, la requête 2 retournera 50 fois plus de lignes que la requête 1. Cela peut être ce que vous voulez, ou pas. Si x est UNIQUE dans les deux tables, les requêtes donneront les mêmes résultats.

(Options sous-requêtes 1 et 2) sont exécutées pour chaque ligne de la requête externe

Ceci est bien sûr faux, puisque les sous-requêtes ne sont pas dépendants les sous-requêtes. Quoi qu'il en soit, il exécutera la sous-requête une fois, et le hachera ou le triera pour éliminer les doublons (comme requis par IN()), puis utilisera la liste résultante pour effectuer une jointure IN. MySQL jusqu'à ce que les versions récentes aient ré-exécuter la sous-requête pour chaque ligne, ce n'est plus le cas. Comme MySQL ne fait pas de hash IN, cela peut être beaucoup plus lent qu'un JOIN.

Questions connexes