2009-03-13 7 views

Répondre

15

Avec un optimiseur de requête décent: il ne devrait pas.

Mais en pratique, je soupçonne qu'il pourrait.

Vous pouvez seulement dire pour vos cas en mesurant. Et les mesures vont probablement changer à mesure que la distribution des données change dans la base de données.

+1

+1: Bien que 99,99% du temps, ce n'est pas grave ... J'ai juste rencontré un problème aujourd'hui où une requête extrêmement simple contre des champs bien indexés était de choisir le mauvais plan d'exécution à moins que l'ordre des deux Les critères de la clause WHERE ont été inversés. Drôle: le planificateur de requêtes a suggéré un index manquant avec exactement les mêmes spécifications que celui choisi par l'optimiseur lorsque j'ai inversé la clause WHERE. Plus drôle: l'ordre des critères qui était le plus rapide était * en retard * par rapport à l'ordre de l'index. Ajouter un indice (ou supprimer ORDER BY) le résout. (J'utilise SQL Server 2005.) –

+0

Vous n'avez pas répondu à la question du tout –

+0

@ JᴀʏMᴇᴇ J'ai. La réponse est: toutes les questions, surtout dans le cas général, n'ont pas de réponse. Ceci est un exemple d'une telle question. – Richard

-4

Si vous êtes dans des conditions AND, la première non vraie renvoie false, donc l'ordre peut affecter les performances.

+0

Je ne vois pas pourquoi cela a été downvoted +1 –

+2

Upvoting parce que vous pensez qu'un downvote était injuste, plutôt que parce que vous croyez que la réponse mérite un upvote n'est pas une bonne pratique. Je crois qu'un optimiseur de requête réorganisera les règles, plutôt que d'utiliser simplement une évaluation paresseuse. – SpoonMeiser

+2

SpoonMeiser est correct; l'optimiseur (au moins pour SQL Server) utilise une logique plus complexe qu'une simple évaluation de style C++. – mwigdahl

2

Tout dépend du SGBD, de l'optimiseur de requêtes et des règles, mais il affecte généralement les performances.

Si une clause where est ordonnée de telle sorte que la première condition réduit significativement le résultat, les conditions restantes n'auront besoin d'être évaluées que pour un ensemble plus petit. Suivant cette logique, vous pouvez optimiser une requête en fonction de l'ordre des conditions dans une clause where.

12

Pour Transact-SQL, il existe une priorité définie pour les opérateurs dans le condition de la clause WHERE. L'optimiseur peut réorganiser cette évaluation, vous ne devez donc pas compter sur le comportement de court-circuit pour l'exactitude. La commande est généralement de gauche à droite, mais la sélectivité/disponibilité des index a probablement aussi son importance. La simplification de votre condition de recherche devrait améliorer la capacité de l'optimiseur à la gérer.

Ex:

WHERE (a OR b) AND (b OR c) 

pourrait être simplifié à

WHERE b OR (a AND c) 

Il est clair que dans ce cas, si l'on peut construire la requête pour trouver si b est titulaire d'abord, il peut être en mesure de sauter l'évaluation d'un et c et courrait ainsi plus vite. Si l'optimiseur peut faire cette transformation simple, je ne peux pas répondre (il peut être capable de), mais le fait est qu'il ne peut probablement pas faire des transformations arbitrairement complexes et vous pouvez effectuer des performances de requête en réorganisant votre condition. Si b est plus sélectif ou a un index, l'optimiseur serait probablement capable de construire une requête en l'utilisant en premier.

EDIT: En ce qui concerne votre question sur commande en fonction de l'unicité, je suppose que les conseils que vous pouvez les fournir à l'optimiseur en fonction de votre connaissance (réelle, et non supposé) des données ne peut pas nuire. Imaginez qu'il ne fera aucune optimisation et construira votre requête comme si vous aviez besoin de la définir du plus sélectif au moins sélectif, mais n'obéissez pas jusqu'à ce que la performance soit réellement un problème.

Je cite la référence ci-dessus:

L'ordre de priorité pour les opérateurs logiques n'est pas (le plus élevé), suivie et, suivi par OR. Les parenthèses peuvent être utilisées pour remplacer cette précédence dans une condition de recherche. L'ordre d'évaluation des opérateurs logiques peut varier en fonction des choix effectués par l'optimiseur de requête .

+1

-1 Il n'y a pas d'ordre d'évaluation défini sauf dans une instruction 'CASE' ou (pour une raison obscure de rétrocompatibilité) lors du chaînage des conditions' EXISTS'. [Voir cet article pour une démonstration] (http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/) –

+0

@MartinSmith - Étant donné que j'ai cité le Documentation T-SQL, je dirais que l'observation de l'auteur que ce n'est pas un bug est discutable. Les docs spécifient clairement que les opérateurs dans une clause WHERE obéissent aux règles de priorité. Bien sûr, il se peut que la documentation soit erronée et j'ai été induit en erreur. – tvanfosson

+1

@tvanfosson - Désolé n'a pas remarqué cette phrase spécifique dans les documents que vous avez basé votre réponse sur si ont rétracté mon DV mais [semble que cela a été corrigé dans les versions ultérieures] (http://technet.microsoft.com/fr -us/library/ms173545.aspx) pour dire 'L'ordre d'évaluation des opérateurs logiques peut varier en fonction des choix effectués par l'optimiseur de requêtes' –

0

Dans la grande majorité des cas l'optimiseur de requêtes déterminera la façon la plus efficace de sélectionner les données que vous avez demandé, quel que soit l'ordre des arguments de recherche définis dans la clause WHERE.

La commande est déterminée par des facteurs tels que la sélectivité de la colonne en question (que SQL Server connaît en fonction des statistiques) et si des index peuvent être utilisés ou non.

6

Pour SQL Server 2000/20005/2008, l'optimiseur de requête vous donnera généralement des résultats identiques quelle que soit la disposition des colonnes dans la clause WHERE. Cela dit, au cours des années d'écriture de milliers de commandes T-SQL, j'ai trouvé quelques cas de coin où l'ordre modifié la performance. Voici quelques caractéristiques des requêtes qui semblaient être soumis à ce problème:

  1. Si vous avez un grand nombre de tables dans votre requête (10 ou plus).

  2. Si vous avez plusieurs EXISTS, IN, NOT EXISTS, ou non énoncés dans la clause WHERE

  3. Si vous utilisez CTE imbriqué de (expressions-table) ou un grand nombre de CTE.

  4. Si vous avez un grand nombre de sous-requêtes dans votre clause FROM.

Voici quelques conseils pour essayer d'évaluer la meilleure façon de résoudre le problème de performance rapidement:

  1. Si le problème est lié à 1 ou 2, puis essayez réorganisant la clause WHERE et comparer le coût du sous-arbre des requêtes dans les plans de requête estimés. Si le problème est lié à 3 ou 4, essayez de déplacer les sous-requêtes et les CTE hors de la requête et demandez-leur de charger les tables temporaires. L'optimiseur de plan de requête est plus efficace pour estimer les plans de requête si vous réduisez le nombre de jointures complexes et de sous-requêtes du corps de l'instruction T-SQL.

  2. Si vous utilisez des tables temporaires, assurez-vous que vous avez spécifié des clés primaires pour les tables temporaires. Cela signifie éviter d'utiliser SELECT INTO FROM pour générer la table. Au lieu de cela, créez explicitement la table et spécifiez une clé primaire avant d'utiliser une instruction INSERT INTO SELECT. Si vous utilisez des tables temporaires et que BEAUCOUP de processus sur le serveur utilisent également des tables temporaires, vous pouvez créer une table intermédiaire plus permanente qui est tronquée et rechargée pendant le processus de requête. Vous êtes plus susceptible de rencontrer des problèmes de conflit de disque si vous utilisez TempDB pour stocker vos tables de travail/de transfert.

  3. Déplacez les instructions de la clause WHERE qui filtrera le plus de données au début de la clause WHERE. S'il vous plaît noter que si c'est votre solution au problème, alors vous aurez probablement de mauvaises performances à nouveau sur la ligne lorsque le plan de requête se confronte à nouveau sur la génération et la sélection du meilleur plan d'exécution. Il est préférable de trouver un moyen de réduire la complexité de la requête afin que l'ordre de la clause WHERE ne soit plus pertinent.

J'espère que vous trouverez cette information utile. Bonne chance!

+0

+1 C'est ce que j'ai trouvé aussi - on vous dit que l'optimiseur va le faire, mais quand vous le mesurez, suggérez autrement. – Fenton

2

En théorie deux requêtes qui sont équivalentes devraient produire des plans de requête identiques. Comme l'ordre des clauses WHERE n'a aucun effet sur la signification logique de la requête, cela signifie que l'ordre de la clause WHERE ne devrait avoir aucun effet.

Cela est dû au fonctionnement de l'optimiseur de requête. Dans une considérablement simplifiée aperçu:

  1. First SQL Server analyse la requête et construit un arbre d'opérateurs logiques (ou SELECTJOIN par exemple).
  2. Puis il traduit ces opérateurs logiques en un "arbre d'opérations physiques" (par exemple "Nested Loops" ou "Index scan", soit un plan d'exécution)
  3. Puis il permute à travers l'ensemble des arbres "équivalents des opérations physic "(c.-à-d. plans d'exécution) en échangeant des opérations équivalentes, en estimant le coût de chaque plan jusqu'à ce qu'il trouve le meilleur.

La deuxième étape se fait est une manière complètement Nieve - il choisit simplement le premier/arbre physique le plus évident qu'il peut, mais dans la 3ème étape l'Optimiseur de requête est en mesure de regarder à travers tous arbres physiques équivalents (c'est-à-dire les plans d'exécution), et tant que les requêtes sont réellement équivalentes, peu importe le plan initial obtenu à l'étape 2, l'ensemble des plans à considérer à l'étape 3 est le même.

(je ne me souviens pas les vrais noms pour les arbres logiques/physiques, ils sont dans un livre, mais malheureusement, le livre est l'autre côté du monde de moi en ce moment)

Voir la série suivante articles de blog pour plus de détails Inside the Optimizer: Constructing a Plan - Part 1

en réalité l'Optimiseur de requête n'a pas cependant souvent l'occasion d'examiner tous arbres équivalent à l'étape 3 (pour les requêtes complexes, il peut y avoir un nombre important de plans possibles), et ainsi après un certain temps de coupure l'étape 3 est coupée court et la requête optimis er doit choisir le meilleur plan qu'il a trouvé jusqu'ici - dans ce cas, pas tous les plans seront considérés. Il y a beaucoup de choses derrière la magie des sceene qui fait que l'optimiseur de requêtes choisit sélectivement et avec discernement les plans à considérer, et donc la plupart du temps, le plan choisi est "assez bon" - même si ce n'est pas le Ce qui signifie cependant que si nous avons un plan de départ différent à l'étape 2 (ce qui peut arriver si nous écrivons différemment), cela signifie potentiellement que le plan est le plus rapide possible. qu'un sous-ensemble différent de plans est considéré à l'étape 3, et donc en théorie SQL Server peut proposer différents plans de requête pour des requêtes équivalentes en fonction de la façon dont ils ont été écrits.

En réalité cependant 99% du temps vous ne remarquerez pas la différence (pour de nombreux plans simples, il n'y aura pas de différence car l'optimiseur prendra en compte tous les plans).De plus, vous ne pouvez pas prédire comment tout cela va fonctionner et donc des choses qui pourraient sembler sensées (comme mettre les clauses WHERE dans un certain ordre), pourraient ne pas avoir quelque chose comme l'effet attendu.

Questions connexes