Les expressions booléennes dans les clauses SQL WHERE sont -elles évaluées en court-circuit ?
Par exemple:
SELECT *
FROM Table t
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key)
Si @key IS NULL prend la valeur true, est-ce que @key IS NOT NULL AND @key = t.Key est évalué?
Si non, pourquoi pas?
Si oui, est-ce garanti? Fait-il partie de ANSI SQL ou est-ce spécifique à une base de données?
Si la base de données est spécifique, SqlServer? Oracle? MySQL?
sql
short-circuiting
Greg Dean
la source
la source
WHERE a = 1 AND b = 2
qu'il pourrait être efficace pour le moteur de base de données de trouver toutes les lignes où b = 2 en premier, puis filtrer où a = 1. Si vous demandez une garantie, l'optimiseur devient inutile.Réponses:
ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf
la source
CASE
est court-circuité.D'après ce qui précède, le court-circuit n'est pas vraiment disponible.
Si vous en avez besoin, je vous suggère une déclaration de cas:
Expr1
est toujours évalué, mais un seul parmiExpr2
etExpr3
sera évalué par ligne.la source
Je pense que c'est l'un des cas où je l'écrirais comme s'il ne court-circuitait pas, pour trois raisons.
Parce que pour MSSQL, ce n'est pas résolu en regardant BOL à l'endroit évident, donc pour moi, cela le rend canoniquement ambigu.
parce qu'au moins je sais que mon code fonctionnera. Et plus important encore, ceux qui viendront après moi le seront aussi, donc je ne les incite pas à s'inquiéter à travers la même question encore et encore.
J'écris assez souvent pour plusieurs produits SGBD et je ne veux pas avoir à me souvenir des différences si je peux les contourner facilement.
la source
Je ne crois pas que les courts-circuits dans SQL Server (2005) soient garantis. SQL Server exécute votre requête via son algorithme d'optimisation qui prend en compte de nombreux éléments (index, statistiques, taille de table, ressources, etc.) pour proposer un plan d'exécution efficace. Après cette évaluation, vous ne pouvez pas dire avec certitude que votre logique de court-circuit est garantie.
J'ai moi-même rencontré la même question il y a quelque temps et mes recherches ne m'ont pas vraiment donné de réponse définitive. Vous pouvez écrire une petite requête pour vous donner un sentiment de preuve que cela fonctionne, mais pouvez-vous être sûr qu'à mesure que la charge de votre base de données augmente, les tables deviennent plus grandes et les choses sont optimisées et modifiées dans la base de données, cette conclusion sera tenir. Je ne pouvais pas et j'ai donc commis une erreur par excès de prudence et utilisé la clause CASE in WHERE pour assurer un court-circuit.
la source
Vous devez garder à l'esprit le fonctionnement des bases de données. Étant donné une requête paramétrée, la base de données construit un plan d'exécution basé sur cette requête sans les valeurs des paramètres. Cette requête est utilisée chaque fois que la requête est exécutée, quelles que soient les valeurs réellement fournies. Que la requête court-circuite avec certaines valeurs n'aura pas d'importance pour le plan d'exécution.
la source
J'utilise généralement ceci pour les paramètres facultatifs. Est-ce la même chose qu'un court-circuit?
Cela me donne la possibilité de passer -1 ou autre pour tenir compte de la vérification facultative d'un attribut. Parfois, cela implique de rejoindre plusieurs tables, ou de préférence une vue.
Très pratique, pas tout à fait sûr du travail supplémentaire qu'il donne au moteur db.
la source
Pour SQL Server, je pense que cela dépend de la version, mais mon expérience avec SQL Server 2000 est qu'il évalue toujours @key = t.Key même lorsque @key est nul. En d'autres termes, il n'effectue pas de court-circuit efficace lors de l'évaluation de la clause WHERE.
J'ai vu des gens recommander une structure comme votre exemple comme moyen de faire une requête flexible où l'utilisateur peut entrer ou non différents critères. Mon observation est que Key est toujours impliqué dans le plan de requête lorsque @key est nul et si Key est indexé, il n'utilise pas l'index efficacement.
Ce type de requête flexible avec des critères variables est probablement un cas où le SQL créé dynamiquement est vraiment la meilleure solution. Si @key est nul, vous ne l'incluez tout simplement pas du tout dans la requête.
la source
Je viens de trébucher sur cette question, et j'avais déjà trouvé cette entrée de blog: http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/
Le serveur SQL est libre d'optimiser une requête partout où il le juge opportun, donc dans l'exemple donné dans l'article de blog, vous ne pouvez pas compter sur un court-circuit.
Cependant, un CASE est apparemment documenté à évaluer dans l'ordre écrit - vérifiez les commentaires de ce billet de blog.
la source
La principale caractéristique de l'évaluation des courts-circuits est qu'elle arrête d'évaluer l'expression dès que le résultat peut être déterminé. Cela signifie que le reste de l'expression peut être ignoré car le résultat sera le même, qu'il soit évalué ou non.
Les opérateurs booléens binaires sont comutatifs, ce qui signifie:
il n'y a donc aucune garantie sur l'ordre d'évaluation. L'ordre d'évaluation sera déterminé par l'optimiseur de requêtes.
Dans les langages avec objets, il peut y avoir des situations dans lesquelles vous pouvez écrire des expressions booléennes qui ne peuvent être évaluées qu'avec une évaluation de court-circuit. Votre exemple de construction de code est souvent utilisé dans ces langages (C #, Delphi, VB). Par exemple:
Cet exemple C # provoquera une exception
someString == null
car il sera entièrement évalué. En évaluation de court-circuit, cela fonctionnera à chaque fois.SQL fonctionne uniquement sur des variables scalaires (pas d'objets) qui ne peuvent pas être non initialisées, il n'y a donc aucun moyen d'écrire une expression booléenne qui ne peut pas être évaluée. Si vous avez une valeur NULL, toute comparaison renverra false.
Cela signifie qu'en SQL, vous ne pouvez pas écrire une expression évaluée différemment en fonction de l'utilisation d'un court-circuit ou d'une évaluation complète.
Si l'implémentation SQL utilise une évaluation de court-circuit, elle ne peut qu'espérer accélérer l'exécution des requêtes.
la source
Je ne sais pas pour une courte diffusion, mais je l'écrirais comme une déclaration if-else
de plus, les variables doivent toujours être du côté droit de l'équation. cela le rend discutable.
http://en.wikipedia.org/wiki/Sargable
la source
Ci-dessous un test rapide et sale sur SQL Server 2008 R2:
Cela revient immédiatement sans aucun enregistrement. Une sorte de comportement de court-circuit était présent.
Alors essayé ceci:
savoir qu'aucun enregistrement ne satisferait à cette condition:
Cela a pris plusieurs secondes, indiquant que le comportement de court-circuit n'était plus là et que l'opération complexe était évaluée pour chaque enregistrement.
J'espère que cela aide les gars.
la source
Voici une démonstration pour prouver que MySQL effectue le court-circuit de la clause WHERE :
http://rextester.com/GVE4880
Cela exécute les requêtes suivantes:
La seule différence entre ceux-ci est l'ordre des opérandes dans la condition OR.
myslowfunction
dort délibérément pendant une seconde et a pour effet secondaire d'ajouter une entrée à une table de journal chaque fois qu'elle est exécutée. Voici les résultats de ce qui est consigné lors de l'exécution des deux requêtes ci-dessus:Ce qui précède montre qu'une fonction lente est exécutée plus de fois lorsqu'elle apparaît sur le côté gauche d'une condition OR lorsque l'autre opérande n'est pas toujours vrai (en raison d'un court-circuit).
la source
Cela prend 4 secondes supplémentaires dans l'analyseur de requêtes, donc d'après ce que je peux voir, IF n'est même pas court-circuité ...
Ce serait bien d'avoir un moyen garanti!
la source
Il est évident que le serveur MS Sql prend en charge la théorie des courts-circuits, pour améliorer les performances en évitant les vérifications inutiles,
Exemple à l'appui:
Ici, le premier exemple entraînerait l'erreur «La conversion a échoué lors de la conversion de la valeur varchar« A »en type de données int.»
Alors que la seconde s'exécute facilement car la condition 1 = 1 évaluée à TRUE et donc la seconde condition ne s'exécute pas du tout.
En outre
ici, la première condition serait évaluée à faux et donc le SGBD irait pour la deuxième condition et vous obtiendrez à nouveau l'erreur de conversion comme dans l'exemple ci-dessus.
REMARQUE: J'ÉCRIT LA CONDITION ERRONEE JUSTE POUR RÉALISER LA MÉTÉO LA CONDITION EST EXÉCUTÉE OU EN COURT-CIRCUIT SI LA REQUÊTE RÉSULTAT EN ERREUR SIGNIFIE LA CONDITION EXÉCUTÉE, EN COURT-CIRCUIT AUTREMENT.
EXPLICATION SIMPLE
Considérer,
comme la première condition est évaluée à TRUE , il est inutile d'évaluer la deuxième condition car son évaluation dans n'importe quelle valeur n'affecterait pas du tout le résultat, donc c'est une bonne opportunité pour Sql Server de gagner du temps d'exécution de la requête en ignorant la vérification ou l'évaluation des conditions inutiles .
dans le cas de "OU" si la première condition est évaluée à TRUE, la chaîne entière connectée par "OR" serait considérée comme évaluée à true sans en évaluer les autres.
si la condition1 est évaluée à vrai, mettez toutes les conditions au repos jusqu'à ce que la conditionN soit ignorée. En termes généralisés lors de la détermination du premier TRUE , toutes les autres conditions liées par OR seraient sautées.
Considérez la deuxième condition
comme la première condition est évaluée à FALSE, il est inutile d'évaluer la deuxième condition car son évaluation dans n'importe quelle valeur n'affecterait pas du tout le résultat, donc encore une fois, c'est une bonne opportunité pour Sql Server de gagner du temps d'exécution de la requête en ignorant la vérification ou l'évaluation des conditions inutiles .
dans le cas de "ET" si la première condition est évaluée à FAUX, la chaîne entière connectée avec le "ET" serait considérée comme évaluée à FAUX sans en évaluer les autres.
si la condition1 est évaluée à FALSE , mettez toutes les conditions au repos jusqu'à ce que la conditionN soit ignorée. En termes généralisés lors de la détermination du premier FALSE , toutes les autres conditions liées par AND seraient ignorées.
PAR CONSÉQUENT, UN PROGRAMMEUR SAGE DOIT TOUJOURS PROGRAMMER LA CHAÎNE DE CONDITIONS DE TELLE FAÇON QUE, LA CONDITION LA MOINS CHER OU LA PLUS ÉLIMINATOIRE SOIT ÉVALUÉE D'ABORD, OU ARRANGER LA CONDITION DE TELLE FAÇON DE PRENDRE UN BÉNÉFICE MAXIMAL DU COURT-CIRCUIT
la source