Source faisant autorité dont <> et! = Ont des performances identiques dans SQL Server

74

Considérez cette réponse sur SO qui rassure le demandeur sur l' <>opérateur que:

<>est ... le même que !=.

Mais ensuite, un intervenant ajoute:

C'est vrai qu'ils sont, fonctionnellement, les mêmes. Cependant, leur utilisation par l'optimiseur SQL est très différente. = /! = sont simplement évalués comme true / false, tandis que <> signifie que le moteur doit rechercher et voir si la valeur est supérieure ou inférieure à, ce qui signifie une surcharge de performances. Juste quelque chose à considérer lors de l'écriture des requêtes qui peuvent être coûteuses.

Je suis convaincu que cela est faux, mais pour répondre aux sceptiques potentiels, je me demande si quelqu'un peut fournir une source faisant autorité ou canonique pour prouver que ces opérateurs ne sont pas seulement fonctionnellement identiques, mais sont identiques à tous égards?

ErikE
la source

Réponses:

144

Lors de l'analyse , SQL Server appelle sqllang!DecodeCompOppour déterminer le type d'opérateur de comparaison présent:

Pile d'appels

Cela se produit bien avant que quoi que ce soit dans l'optimiseur ne soit impliqué.

À partir d' opérateurs de comparaison (Transact-SQL)

Opérateurs de comparaison et significations

Le traçage du code à l'aide d'un débogueur et de symboles publics * sqllang!DecodeCompOprenvoie une valeur dans le registre eax** comme suit:

╔════╦══════╗
║ Op ║ Code ║
╠════╬══════╣
║ <  ║    1 ║
║ =  ║    2 ║
║ <= ║    3 ║
║ !> ║    3 ║
║ >  ║    4 ║
║ <> ║    5 ║
║ != ║    5 ║
║ >= ║    6 ║
║ !< ║    6 ║
╚════╩══════╝

!=et les <>deux retournent 5, sont donc indiscernables dans toutes les opérations ultérieures (y compris la compilation et l'optimisation).


Bien que secondaire au point ci - dessus, il est également possible (par exemple en utilisant l' indicateur de trace sans papier 8605) pour regarder l'arbre logique est passé à l'optimiseur pour confirmer que les deux !=et la <>carte à ScaOp_Comp x_cmpNe(pas égale comparaison de l' opérateur scalaire).

Par exemple:

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID != 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

SELECT P.ProductID FROM Production.Product AS P
WHERE P.ProductID <> 4
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);

les deux produisent:

LogOp_Project QCOL: [P] .ProductID
    LogOp_Select
        LogOp_Get TBL: Production.Product (alias TBL: P)
        ScaOp_Comp x_cmpNe
            ScaOp_Identifier QCOL: [P] .ID du produit
            ScaOp_Const TI (int, ML = 4) XVAR (int, non possédé, valeur = 4)
    AncOp_PrjList 

Notes de bas de page

* J'utilise WinDbg ; d'autres débogueurs sont disponibles. Les symboles publics sont disponibles via le serveur de symboles Microsoft habituel. Pour plus d'informations, voir Approfondissement de SQL Server à l'aide de Minidumps par l'équipe de conseil aux clients SQL Server et Débogage de SQL Server avec WinDbg - Introduction de Klaus Aschenbrenner.

** L'utilisation de EAX sur des dérivés 32 bits d'Intel pour renvoyer les valeurs d'une fonction est courante. Certes, l’ABI Win32 le fait de cette façon, et je suis à peu près sûr qu’il hérite de cette pratique de l’ancien système MS-DOS, où AX était utilisé dans le même but - Michael Kjörling

Paul White
la source
58

Je travaille chez Microsoft dans le support SQL et j'ai demandé à Jack Li, ingénieur principal en escalade et expert en la matière des performances SQL Server, "SQL traite-t-il! = Différemment de <>?" et il a dit: "Ils sont les mêmes."

Stacylaray
la source
8

Je pense que ce qui suit prouve que <>ne fait pas 2 comparaisons.

  1. La norme SQL 92 définit <>les opérateurs non égaux ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Techniquement, !=c'est une extension de la norme (même si je ne peux pas penser à un SGBDR qui ne l'implémente pas).
  2. Si SQLServer traité <>comme 2 opérateurs, pas un, il ferait la même chose, ><ce qui est en fait une erreur de syntaxe.
a1ex07
la source
1

C'est incorrect, Books Online (BOL) dit qu'ils sont fonctionnellement identiques:

! = (Différent de) (Transact-SQL)

Et si vous regardez un plan d'exécution où !=est utilisé, sous prédicats, il change != à <>.

Ryan Cooper
la source
2
Le problème est que le langage "fonctionnellement le même" est déjà admis dans le commentaire référencé, mais fait une distinction supplémentaire sur les performances, malgré votre connaissance et celle dont vous êtes conscient que "fonctionnellement identique" inclut son fonctionnement réel et ses caractéristiques de performances. Si on voulait prouver cela au-delà de tout scepticisme déterminé, que ferait-on?
ErikE