Sumber resmi yang <> dan! = Identik dalam kinerja di SQL Server

74

Pertimbangkan jawaban ini di SO yang meyakinkan penanya tentang <>operator bahwa:

<>adalah ... sama dengan !=.

Tapi kemudian seorang komentator menjawab dan berkata:

Memang benar bahwa secara fungsional mereka sama. Namun, bagaimana pengoptimal SQL menggunakannya sangat berbeda. = /! = secara sederhana dievaluasi sebagai benar / salah sedangkan <> berarti mesin harus melihat dan melihat apakah nilainya lebih dari atau kurang dari, yang berarti lebih banyak overhead kinerja. Hanya sesuatu yang perlu dipertimbangkan ketika menulis pertanyaan yang mungkin mahal.

Saya yakin ini salah, tetapi untuk mengatasi potensi skeptis, saya bertanya-tanya apakah ada yang bisa memberikan sumber otoritatif atau kanonik untuk membuktikan bahwa operator ini tidak hanya secara fungsional sama, tetapi identik dalam semua aspek?

ErikE
sumber

Jawaban:

144

Selama parsing , SQL Server panggilan sqllang!DecodeCompOpuntuk menentukan jenis operator perbandingan yang ada:

Tumpukan panggilan

Ini terjadi jauh sebelum apa pun dalam pengoptimal terlibat.

Dari Operator Perbandingan (Transact-SQL)

Operator perbandingan dan makna

Menelusuri kode menggunakan debugger dan simbol publik *, sqllang!DecodeCompOpmengembalikan nilai dalam register eax** sebagai berikut:

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

!=dan <>keduanya menghasilkan 5, sehingga tidak dapat dibedakan dalam semua operasi selanjutnya (termasuk kompilasi & optimisasi).


Meskipun sekunder untuk titik di atas, dimungkinkan juga (misalnya menggunakan jejak bendera tidak berdokumen 8605) untuk melihat pohon logis yang diteruskan ke pengoptimal untuk mengkonfirmasi keduanya !=dan <>memetakannya ScaOp_Comp x_cmpNe(bukan perbandingan operator skalar yang sama).

Sebagai contoh:

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

keduanya menghasilkan:

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, Tidak Dimiliki, Nilai = 4)
    AncOp_PrjList 

Catatan kaki

* Saya menggunakan WinDbg ; debuggers lain tersedia. Simbol publik tersedia melalui server simbol Microsoft yang biasa. Untuk informasi lebih lanjut, lihat Melihat lebih dalam ke SQL Server menggunakan Minidumps oleh Tim Penasihat Pelanggan SQL Server dan SQL Server Debugging dengan WinDbg - sebuah Pengantar oleh Klaus Aschenbrenner.

** Menggunakan EAX pada turunan Intel 32-bit untuk nilai pengembalian dari suatu fungsi adalah hal biasa. Tentu saja Win32 ABI melakukannya dengan cara itu, dan saya cukup yakin itu mewarisi praktik itu dari masa MS-DOS, di mana AX digunakan untuk tujuan yang sama - Michael Kjörling

Paul White
sumber
58

Saya bekerja di Microsoft dalam Dukungan SQL dan saya bertanya kepada Jack Li, Insinyur Eskalasi Senior, dan Ahli Perihal Kinerja SQL Server, "Apakah SQL memperlakukan! = Berbeda dengan <>?" dan dia berkata, "Mereka sama."

stacylaray
sumber
8

Saya pikir berikut ini membuktikan bahwa <>tidak melakukan 2 perbandingan.

  1. SQL Standard 92 didefinisikan <>sebagai tidak sama dengan operator, ( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt ). Secara teknis, !=ini merupakan perpanjangan dari standar (walaupun saya tidak bisa memikirkan RDBMS yang tidak mengimplementasikannya).
  2. Jika SQLServer diperlakukan <>sebagai 2 operator, bukan satu, itu akan melakukan hal yang sama ><yang sebenarnya adalah kesalahan sintaks.
a1ex07
sumber
1

Itu tidak benar, Books Online (BOL) mengatakan mereka secara fungsional sama:

! = (Tidak Setara) (Transact-SQL)

Dan jika Anda melihat rencana eksekusi di mana !=digunakan, di bawah Predikat, itu berubah != menjadi <>.

Ryan Cooper
sumber
2
Masalahnya adalah bahwa bahasa "secara fungsional sama" sudah diterima dalam komentar yang direferensikan, tetapi membuat perbedaan tambahan tentang kinerja, terlepas dari pengetahuan Anda dan saya bahwa "secara fungsional sama" termasuk cara kerjanya dan karakteristik kinerja apa pun daripadanya. Jika seseorang ingin membuktikan ini di luar semua skeptisisme, apa yang akan dilakukan?
ErikE