Compte tenu de cette question sur reddit, j'ai nettoyé la requête pour indiquer où se trouvait le problème dans la requête. J'utilise d'abord des virgules et WHERE 1=1
pour faciliter la modification des requêtes, mes requêtes se terminent généralement comme suit:
SELECT
C.CompanyName
,O.ShippedDate
,OD.UnitPrice
,P.ProductName
FROM
Customers as C
INNER JOIN Orders as O ON C.CustomerID = O.CustomerID
INNER JOIN [Order Details] as OD ON O.OrderID = OD.OrderID
INNER JOIN Products as P ON P.ProductID = OD.ProductID
Where 1=1
-- AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
And P.productname = 'TOFU'
Order By C.CompanyName
Quelqu'un a essentiellement dit que 1 = 1 est généralement paresseux et mauvais pour les performances .
Étant donné que je ne veux pas "optimiser prématurément" - je veux suivre les bonnes pratiques. J'ai déjà examiné les plans de requête, mais généralement uniquement pour savoir quels index je peux ajouter (ou ajuster) pour accélérer l'exécution de mes requêtes.
La question est alors vraiment ... de Where 1=1
provoquer de mauvaises choses? Et si oui, comment savoir?
Édition mineure: j'ai toujours `` supposé '' que ce 1=1
serait optimisé, ou au pire négligeable. Ne fait jamais de mal à remettre en question un mantra, comme "Goto's are Evil" ou "Premature Optimization ..." ou d'autres faits supposés. Je ne savais pas si 1=1 AND
cela affecterait ou non les plans de requête de manière réaliste. Et dans les sous-requêtes? CTE? Procédures?
Je ne suis pas du genre à optimiser, sauf si c'est nécessaire ... mais si je fais quelque chose qui est réellement "mauvais", je voudrais minimiser les effets ou changer le cas échéant.
la source
Réponses:
Le serveur SQL
analyseurL'optimiseur a une fonction appelée "Pliage constant" qui élimine les expressions tautologiques de la requête.Si vous regardez le plan d'exécution, nulle part dans les prédicats, vous ne verrez cette expression apparaître. Cela implique que le pliage constant est effectué de toute façon au moment de la compilation pour cela et pour d'autres raisons et cela n'a aucun effet sur les performances des requêtes.
Voir Évaluation du pliage constant et de l'expression pendant l'estimation de la cardinalité pour plus d'informations.
la source
L'ajout du prédicat redondant peut faire une différence dans SQL Server.
Dans les plans d'exécution ci-dessous, notez le
@1
dans le premier plan par rapport au littéral'foo'
dans le deuxième plan.Cela indique que SQL Server a considéré la première requête de paramétrage simple pour promouvoir la réutilisation du plan d'exécution - cependant la comparaison de deux constantes empêche cela de se produire dans le second cas.
Une liste de conditions qui empêchent le paramétrage simple (anciennement connu sous le nom de paramétrisation automatique) se trouve à l'annexe A des plans techniques de mise en cache de Microsoft:
le paramétrage simple n'est généralement pas quelque chose sur lequel vous devriez compter de toute façon. Il est préférable de paramétrer explicitement vos requêtes.
la source
Dans tout SGBDR moderne (y compris Oracle, Microsoft SQL Server et PostgreSQL - j'en suis sûr), cela n'aura aucun effet sur les performances.
Comme quelqu'un l'a noté, cela n'affectera que la phase de planification des requêtes. Par conséquent, la différence ne sera visible que lorsque vous exécutez des milliers d'itérations d'une requête simpliste qui ne renvoie aucune donnée, comme celle-ci:
Pour moi, sur PostgreSQL 9.0, cela est visible avec seulement 10000 itérations:
la source
Cela peut être un "problème" pour Oracle lorsque vous utilisez le paramètre de base de données cursor_sharing. Lorsque ce paramètre est défini sur "forcer", il modifie toutes les instructions SQL. Toutes les "constantes" des requêtes seront remplacées par des variables de liaison (comme 1 =>: SYS_0).
Cette option a été introduite pour gérer certains développeurs paresseux. D'un autre côté, cela peut également nuire à d'autres développeurs paresseux. Mais le risque n'est pas trop élevé. Depuis 11g, il a une fonction de furtivité variable.
la source