web-dev-qa-db-ja.com

<>と!=がSQL Serverのパフォーマンスで同一である信頼できるソース

考慮してください この答え on SOこれは<>演算子:

<>は...と同じです!=

しかし、その後、コメンターはパイプで言い、

それらが機能的に同じであるのは事実です。ただし、SQLオプティマイザがそれらを使用する方法は大きく異なります。 = /!=は単にtrue/falseとして評価されますが、<>はエンジンが値が大きいか小さいかを調べて確認する必要があることを意味し、パフォーマンスのオーバーヘッドが大きくなります。コストがかかる可能性のあるクエリを作成する際に考慮すべきことの1つ。

これは間違いだと確信していますが、潜在的な懐疑論者に対処するために、これらの演算子が機能的に同じだけでなく、すべての点で同一であることを証明するための信頼できるまたは正規のソースを提供できる人がいるのではないでしょうか。

79
ErikE

解析中に、SQL Serverはsqllang!DecodeCompOpを呼び出して、存在する比較演算子のタイプを判別します。

Call stack

これは、オプティマイザの何かが関与するかなり前に発生します。

From 比較演算子(Transact-SQL) から

Comparison operators and meanings

デバッガとパブリックシンボル*を使用してコードをトレースすると、sqllang!DecodeCompOpは次のようにレジスタeax **に値を返します。

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

!=<>はどちらも5を返すため、区別できない以降のすべての操作(コンパイルと最適化を含む)ではそうです。


上記のポイントの二次的なものですが、(たとえば、文書化されていないトレースフラグ8605を使用して)オプティマイザに渡された論理ツリーを調べて、!=<>の両方がScaOp_Comp x_cmpNeにマップされていることを確認することもできます(スカラー演算子の比較と等しくない)。

例えば:

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

両方が生成します:

 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 

脚注

* WinDbg を使用します。他のデバッガが利用可能です。パブリックシンボルは、通常のMicrosoftシンボルサーバーを介して利用できます。詳細については、SQL Serverカスタマーアドバイザリーチームによる Minidumpsを使用したSQL Serverの詳細 およびKlaus Aschenbrennerによる WinDbgによるSQL Serverデバッグ–はじめに を参照してください。

**関数からの戻り値に32ビットIntel派生でEAXを使用することは一般的です。確かにWin32 ABIはそのようにしており、AXが同じ目的で使用されていた昔のMS-DOSの時代からその慣習を継承していると確信しています- MichaelKjörling

149
Paul White 9

私はSQLサポートでマイクロソフトに勤務し、SQLサーバーのパフォーマンスの上級エスカレーションエンジニアであり、サブジェクトマターエキスパートであるジャックリーに「SQLは!=を<>とは異なるものとして扱いますか?」と尋ねました。そして彼は言った、「彼らは同じです。」

60
stacylaray

次のことが<>は2つの比較を行いません。

  1. SQL標準92は<> as not equals operator、( http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt )。技術的には、!=は標準への拡張です(実装されていないRDBMSについて考えることはできませんが)。
  2. SQLServerが扱った場合<>は1つの演算子ではなく2つの演算子として、><実際には構文エラーです。
8
a1ex07

それは正しくない、Books Online(BOL)は機能的には同じだと言っている。

!=(等しくない)(Transact-SQL)

そして、もしあなたが!=が使用され、[述語]でchanges!=から<>

1
Ryan Cooper