Origine autorevole che <> e! = Hanno prestazioni identiche in SQL Server


74

Considera questa risposta su SO che rassicura chi chiede <>all'operatore che:

<>è ... lo stesso di !=.

Ma poi un commentatore dice e dice:

È vero che sono, funzionalmente, uguali. Tuttavia, il modo in cui l'ottimizzatore SQL li utilizza è molto diverso. = /! = vengono semplicemente valutati come vero / falso mentre <> indica che il motore deve guardare e vedere se il valore è maggiore o minore di, il che significa un maggior sovraccarico di prestazioni. Solo qualcosa da considerare quando si scrivono query che possono essere costose.

Sono sicuro che ciò sia falso, ma per rispondere ai potenziali scettici, mi chiedo se qualcuno può fornire una fonte autorevole o canonica per dimostrare che questi operatori non sono solo funzionalmente uguali, ma identici sotto tutti gli aspetti?

Risposte:


144

Durante l'analisi , SQL Server chiama sqllang!DecodeCompOpper determinare il tipo di operatore di confronto presente:

Call stack

Ciò si verifica molto prima che venga coinvolto qualcosa nell'ottimizzatore.

Da operatori di confronto (Transact-SQL)

Operatori e significati di confronto

Tracciare il codice utilizzando un debugger e simboli pubblici *, sqllang!DecodeCompOprestituisce un valore nel registro eax** come segue:

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

!=ed <>entrambi restituiscono 5, quindi sono indistinguibili in tutte le operazioni successive (inclusi compilazione e ottimizzazione).


Sebbene secondario rispetto al punto precedente, è anche possibile (ad es. Usare il flag di traccia non documentato 8605) guardare l'albero logico passato all'ottimizzatore per confermare che entrambi !=e <>mappare su ScaOp_Comp x_cmpNe(non uguale confronto operatore scalare).

Per esempio:

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

entrambi producono:

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 

Le note

* Uso WinDbg ; sono disponibili altri debugger. I simboli pubblici sono disponibili tramite il solito server dei simboli Microsoft. Per ulteriori informazioni, vedere Approfondimento su SQL Server utilizzando Minidumps dal team di consulenza clienti di SQL Server e debug di SQL Server con WinDbg, un'introduzione di Klaus Aschenbrenner.

** L'uso di EAX su derivati ​​Intel a 32 bit per ottenere valori di ritorno da una funzione è comune. Certamente l'ABI Win32 lo fa in questo modo, e sono abbastanza sicuro che eredita quella pratica dai vecchi tempi di MS-DOS, dove AX era usato per lo stesso scopo - Michael Kjörling


58

Lavoro presso Microsoft nel supporto SQL e ho chiesto a Jack Li, Senior Escalation Engineer e Subject Matter Expert delle prestazioni di SQL Server, "SQL tratta! = In modo diverso da <>?" e disse: "Sono gli stessi".


8

Penso che quanto segue dimostri che <>non fa 2 confronti.

  1. Lo standard SQL 92 definisce <>come non uguale all'operatore ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Tecnicamente, !=è un'estensione dello standard (anche se non riesco a pensare a nessun RDBMS che non lo implementa).
  2. Se SQLServer trattasse <>come 2 operatori, non uno, farebbe lo stesso per i ><quali è in realtà un errore di sintassi.

1

Ciò non è corretto, Books Online (BOL) afferma che sono funzionalmente uguali:

! = (Non uguale a) (Transact-SQL)

E se si guarda a un piano di esecuzione in cui !=viene utilizzato, in predicato, si cambia != a <>.


2
Il problema è che il linguaggio "funzionalmente uguale" è già ammesso nel commento di riferimento, ma fa un'ulteriore distinzione sulle prestazioni, nonostante la vostra e mia conoscenza che "funzionalmente lo stesso" includa il modo in cui funziona effettivamente e le sue caratteristiche prestazionali. Se uno volesse provare questo oltre ogni determinato scetticismo, cosa farebbe?
ErikE,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.