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


74

SO に関するこの回答を検討してください。これにより、<>オペレーターに関する質問者は次のことを安心できます。

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

しかし、その後、コメンターがパイプを使って言います:

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

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

回答:


144

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

呼び出し履歴

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

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

比較演算子と意味

デバッガーとパブリックシンボル*を使用してコードをトレースすると、次のよう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(エイリアス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カスタマーアドバイザリーチームによるミニダンプを使用したSQL Serverの詳細と、WinDbgによるSQL Serverのデバッグ -Klaus Aschenbrennerによる紹介を参照してください。

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


58

MicrosoftのSQLサポートで働いており、SQL Serverパフォーマンスの上級エスカレーションエンジニアおよび主題エキスパートであるJack Liに、「SQLは<>とは異なる処理をしますか?」彼は言った、「彼らは同じです。」


8

次のこと<>は、2つの比較を行わないことを証明していると思います。

  1. SQL Standard 92では<>、等しくない演算子として定義されていますhttp://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)。技術的に!=は、標準を拡張したものです(それを実装していないRDBMSは考えられませんが)。
  2. SQLServerが<>1つではなく2つの演算子として扱われた場合><、実際には構文エラーであるため、同じことを行います。

1

それは間違っています、Books Online(BOL)は機能的には同じだと言います:

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

あなたが実行計画を見ればと!=述語の下で、使用されている、それが変わる !=まで<>


2
問題は、「機能的に同じ」という言語が参照コメントで既に認められているが、「機能的に同じ」には実際の動作とそのパフォーマンス特性が含まれているというあなたと私の知識にもかかわらず、パフォーマンスについてさらに区別することです。これをすべての断固とした懐疑論を超えて証明しようとするなら、何をするでしょうか?
エリック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.