Autorytatywne źródło, które <> i! = Są identyczne pod względem wydajności w SQL Server


74

Rozważ tę odpowiedź na piśmie SO, która zapewnia pytającego o <>operatora, że:

<>jest ... taki sam jak !=.

Ale potem komentator wypowiada się i mówi:

Prawdą jest, że są funkcjonalnie takie same. Jednak sposób ich wykorzystania przez optymalizator SQL jest zupełnie inny. = /! = są po prostu oceniane jako prawda / fałsz, podczas gdy <> oznacza, że ​​silnik musi spojrzeć i zobaczyć, czy wartość jest większa czy mniejsza niż, co oznacza większy narzut wydajności. Tylko coś do rozważenia przy pisaniu zapytań, które mogą być drogie.

Jestem pewien, że to nieprawda, ale w celu zajęcia się potencjalnymi sceptykami zastanawiam się, czy ktoś może dostarczyć wiarygodne lub kanoniczne źródło, aby udowodnić, że operatorzy nie są funkcjonalnie tacy sami, ale we wszystkich aspektach identyczni?

Odpowiedzi:


144

Podczas analizowania wywołania programu SQL Server w sqllang!DecodeCompOpcelu ustalenia rodzaju obecnego operatora porównania:

Stos wywołań

Dzieje się to na długo przed zaangażowaniem się w optymalizator.

Od operatorów porównania (Transact-SQL)

Operatory porównania i znaczenia

Śledzenie kodu za pomocą debugera i symboli publicznych * sqllang!DecodeCompOpzwraca wartość w rejestrze eax** w następujący sposób:

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

!=i <>oba zwracają 5, więc są nierozróżnialne we wszystkich późniejszych operacjach (łącznie z kompilacją i optymalizacją).


Chociaż wtórne do powyższego punktu, możliwe jest również (np. Użycie nieudokumentowanej flagi śledzenia 8605) spojrzenie na drzewo logiczne przekazane do optymalizatora w celu potwierdzenia tego !=i <>odwzorowania na ScaOp_Comp x_cmpNe(nierównomierne porównanie operatorów skalarnych).

Na przykład:

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);

oba wytwarzają:

LogOp_Project QCOL: [P] .ProductID
    LogOp_Select
        LogOp_Get TBL: Production.Product (alias TBL: P)
        ScaOp_Comp x_cmpNe
            ScaOp_Identifier QCOL: [P] .ProductID
            ScaOp_Const TI (int, ML = 4) XVAR (int, Not Owned, Value = 4)
    AncOp_PrjList 

Przypisy

* Używam WinDbg ; dostępne są inne debugery. Symbole publiczne są dostępne za pośrednictwem zwykłego serwera symboli Microsoft. Aby uzyskać więcej informacji, zobacz Zagłębianie się w SQL Server przy użyciu programu Minidumps przez zespół doradców klienta SQL Server i debugowanie programu SQL Server za pomocą WinDbg - wprowadzenie Klausa Aschenbrennera.

** Używanie EAX w 32-bitowych instrumentach pochodnych Intela do zwracania wartości z funkcji jest powszechne. Z pewnością Win32 ABI robi to w ten sposób i jestem pewien, że dziedziczy tę praktykę po dawnych czasach MS-DOS, w których AX był używany do tego samego celu - Michael Kjörling


58

Pracuję w Microsoft w dziale obsługi SQL i zapytałem Jacka Li, starszego inżyniera ds. Eskalacji i eksperta w temacie wydajności SQL Server: „Czy SQL traktuje! = Inaczej niż <>?” i powiedział: „Są tacy sami”.


8

Myślę, że następujące dowodzi, że <>nie wykonuje 2 porównań.

  1. SQL Standard 92 definiuje <>jako operator nie równy ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Technicznie !=jest rozszerzeniem standardu (chociaż nie mogę myśleć o żadnym systemie RDBMS, który go nie implementuje).
  2. Gdyby SQLServer był traktowany <>jak 2 operatory, a nie jeden, zrobiłby to samo, ><co w rzeczywistości jest błędem składni.

1

To nieprawda, Books Online (BOL) twierdzi, że są funkcjonalnie takie same:

! = (Not Equal To) (Transact-SQL)

A jeśli spojrzysz na plan wykonania, w którym !=jest używany, w Predicate zmienia się != na <>.


2
Problem polega na tym, że język „funkcjonalnie ten sam” jest już dopuszczony w cytowanym komentarzu, ale wprowadza dodatkowe rozróżnienie dotyczące wydajności, pomimo twojej i mojej wiedzy, że „funkcjonalnie ten sam” obejmuje to, jak faktycznie działa i wszelkie jego cechy wydajnościowe. Gdyby ktoś chciał udowodnić, że jest to ponad wszelką determinację, to co by zrobił?
ErikE
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.