L'ordre des clauses where est-il important dans SQL?


121

Disons que j'ai une table appelée PEOPLEayant 3 colonnes ID, LastName, FirstName, aucune de ces colonnes n'est indexée.
LastNameest plus unique et FirstNameest moins unique.

Si je fais 2 recherches:

select * from PEOPLE where FirstName="F" and LastName="L" 
select * from PEOPLE where LastName="L" and FirstName="F"

Ma conviction est que le second est plus rapide car le critère le plus unique ( LastName) vient en premier dans la whereclause, et les enregistrements seront éliminés plus efficacement. Je ne pense pas que l'optimiseur soit assez intelligent pour optimiser le premier sql.

Ma compréhension est-elle correcte?


8
Non, cet ordre n'a pas d'importance - tout optimiseur de requête décent examinera toutes les clauses WHERE et trouvera le moyen le plus efficace de satisfaire cette requête
marc_s

3
Quelles ont été vos observations lorsque vous avez fait ces deux déclarations? À quoi ressemblaient les plans d'exécution?
Conrad Frix du

3
Faites-vous référence à un SGBDR spécifique? Il y a effectivement des différences.
Bjoern du


Réponses:


101

Non, cet ordre n'a pas d'importance (ou du moins: ne devrait pas avoir d'importance).

Tout optimiseur de requête décent examinera toutes les parties duWHERE clause et trouvera le moyen le plus efficace de satisfaire cette requête.

Je sais que l'optimiseur de requêtes SQL Server choisira un index approprié - quel que soit l'ordre dans lequel vous avez vos deux conditions. Je suppose que d'autres SGBDR auront des stratégies similaires.

Ce qui compte, c'est que vous ayez ou non un index approprié pour cela!

Dans le cas de SQL Server, il utilisera probablement un index si vous avez:

  • un index sur (LastName, FirstName)
  • un index sur (FirstName, LastName)
  • un index sur juste (LastName), ou juste (FirstName)(ou les deux)

D'un autre côté - encore une fois pour SQL Server - si vous utilisez SELECT *pour récupérer toutes les colonnes d'une table et que la table est plutôt petite, il y a de fortes chances que l'optimiseur de requête effectue simplement une analyse de table (ou d'index clusterisé) au lieu d'utiliser un index (car la recherche dans la page de données complète pour obtenir toutes les autres colonnes devient tout simplement trop coûteuse très rapidement).


S'il n'y a pas d'index, l'op pourrait être correct, en fonction des données. Bien sûr, faire quelque chose comme ça sans index serait une décision étrange ...
Tony Hopkinson

@TonyHopkinson: Je ne pense pas - même sans index, je doute qu'il y ait une différence. Après tout: sans index, qu'est-ce que le SGBDR peut faire d'autre qu'une analyse complète de la table?
marc_s

2
Note latérale intéressante avec le serveur SQL, apparemment l'ordre de NOT EXISTS dans les prédicats peut en fait influencer la création du plan: bradsruminations.blogspot.com/2010/04/looking-under-hood.html
Justin Swartsel

3
Une chose étrange est que pour la première exécution d'une requête, l'ordre des conditions dans une clause WHERE COMPTE! J'avais deux conditions, quelque chose comme: WHERE T1.col_1/T2.col_2 > 10 AND T2.col_2 <> 0et j'ai eu une DIVIDE BY 0erreur. Après avoir changé l'ordre les conditions, la requête s'est exécutée avec succès. Ensuite, j'ai inversé la commande pour que je m'attende à obtenir l'erreur à nouveau, mais cette fois, cela a fonctionné! En fin de compte, ma conclusion a été que pour la première exécution, la commande importe, jusqu'à ce que le plan d'exécution soit construit. 'Peu importe' car le plan d'optimisation / d'exécution s'en chargera
Radu Gheorghiu

1
J'aime que vous disiez, "... ou du moins: ça ne devrait pas avoir d'importance" - Je suis totalement d'accord. Parfois, cela compte, malheureusement. J'ai vu des cas où SQL était trop complexe pour que l'optimiseur puisse gérer et, et des choses comme l'ordre des colonnes et l'ordre de jointure des tables ont fait une différence. Cela dépend du SGBDR, de la complexité de l'instruction SQL et même de la version. Un SQL très complexe peut entraîner de mauvaises décisions d'optimisation ou l'utilisation de valeurs par défaut codées en dur dans le code de l'optimiseur.
Victor Di Leo

19

L'ordre des clauses WHERE ne doit pas faire de différence dans une base de données conforme à la norme SQL. L'ordre d'évaluation n'est pas garanti dans la plupart des bases de données.

Ne pensez pas que SQL se soucie de l'ordre. Ce qui suit génère une erreur dans SQL Server:

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

Si la première partie de cette clause était exécutée en premier, seuls les noms de table numériques seraient convertis en entiers. Cependant, il échoue, fournissant un exemple clair que SQL Server (comme avec d'autres bases de données) ne se soucie pas de l'ordre des clauses dans l'instruction WHERE.


Qu'est-ce que cette requête provoquant une erreur a à voir avec l'ordre d'évaluation du prédicat WHERE?
Jim

7
@Jim If a ISNUMERIC(table_name) = 1été évalué en premier, alors CASTne serait appelé que pour les noms de table numériques. Mais comme il n'est pas évalué en premier, il CASTest également évalué pour les noms de table non numériques, ce qui provoque le message d'erreur.
hibbelig

2
Excellente clarification
neeohw

Juste pour être sûr que j'ai vérifié si l'échange des conditions amènerait le serveur SQL à les gérer dans l'autre sens, mais cela échoue dans les deux sens. Je pense que cela peut signifier l'une ou l'autre des deux choses suivantes: (1) Ce n'est pas l'optimisation aussi bien que possible ou (2) C'est une erreur de compilation et SQL ne commence même pas à essayer de comparer quoi que ce soit, renflouant les préliminaires. Je suppose que c'est nr. 2.
Louis Somers

9

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3 Ordre d'évaluation des règles

...

Lorsque la priorité n'est pas déterminée par les formats ou par des parenthèses, une évaluation efficace des expressions est généralement effectuée de gauche à droite. Cependant, le fait que les expressions soient réellement évaluées de gauche à droite dépend de l'implémentation, en particulier lorsque des opérandes ou des opérateurs peuvent provoquer le déclenchement de conditions ou si les résultats des expressions peuvent être déterminés sans évaluer complètement toutes les parties de l'expression.

copié d' ici


2

Non, tous les RDBM commencent d'abord par analyser la requête et l'optimiser en réorganisant votre clause where.

En fonction du RDBM que vous utilisez, vous pouvez afficher le résultat de l'analyse (recherchez le plan d'explication dans Oracle par exemple)

M.


Il le fait sur la base d'index. C'est donc indirect en termes de contenu.
Tony Hopkinson

1

Déclaration OP originale

Ma conviction est que la seconde est plus rapide parce que le critère le plus unique (LastName) vient en premier> dans la clause where, et les enregistrements seront éliminés plus efficacement. Je ne pense pas que l'optimiseur> soit assez intelligent pour optimiser le premier sql.

Je suppose que vous confondez cela avec la sélection de l'ordre des colonnes tout en créant les index dans lesquels vous devez placer les colonnes les plus sélectives en premier que les deuxièmes les plus sélectives et ainsi de suite.

BTW, pour les deux requêtes ci-dessus, l'optimiseur de serveur SQL ne fera aucune optimisation mais utilisera le plan Trivila tant que le coût total du plan est inférieur au coût du seuil de parallélisme.


0

C'est vrai pour autant, en supposant que les noms ne soient pas indexés. Des données différentes rendraient les choses erronées cependant. Afin de trouver la manière de le faire, qui pourrait différer à chaque fois, le SGBD devrait exécuter une requête de comptage distincte pour chaque colonne et comparer les nombres, ce qui coûterait plus que simplement hausser les épaules et continuer.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.