LoginSignup
0

More than 1 year has passed since last update.

ヨーダ記法はインデックスの夢を見るか

Posted at

前文

WHERE   (Col1 = 1 OR Col2 =1)

上記のようなクエリは以下のように正規化(?)することができる。

WHERE   1 IN (Col1, Col2)

少しだけ単純になる。「仕様変更に強い」かは置いといて。
面白いのは結果として、所謂 ヨーダ記法 になること。
ヨーダ記法の是非はここでは論じない。それよりも問題はインデックスが効くのかこれ? という素朴な疑問。クエリである以上。
ざっとぐぐったところ答えが見つからなかった(クエリでヨーダ記法なんて普通書かないだろうし)ので確認した次第。

環境

SQLServer SQLCMD
2017 14.0.1000.169

設定はデフォルト。

結論

効く。

そもそも IN句とは、OR で連結した等式の シンタックスシュガー

WHERE   Col1 IN (1, 2)

よく IN句の説明で、上記のクエリは以下のクエリと同じ、みたいな説明を見かける。

WHERE   (Col1 = 1 OR Col1 = 2)

同じも何も、IN句は内部的には後者のように展開される。IN句を直接解釈できる DB なんて自分が知る限り存在しない。(多分)
IN句の括弧の中身が SELECT文のケースを除き、値がリストとして列挙されている場合、機械的に OR で連結した等式に置き換えることができるから。
そうすれば後は通常のクエリとして処理することができるし、わざわざ IN句専用の実行プランを実装する必要はない。

余談ついでに。
長年三項演算子(条件演算子)的な機能が求められていた SQLServer。
よく掲示板でも、SQLServer で三項演算子みたいなことを行いたい場合は? といった質問に対して、CASE式で代用してくださいというやり取りが定番だった。
それが 2012 から IIF関数 が追加された。でもこれって恐らく内部的には CASE式に展開されているんだよね。つまり、CASE式のシンタックスシュガー。
システムとして用意されたのは有難いけど。

で、話をヨーダ記法に戻す。実行プランを確認したら以下だった。

そもそも 1 = Col1 でもインデックスは効くんだね。

因みに上記は Col1 が主キーだけど、キーが張られていない場合は以下だった。

OR で連結した等式に置き換えるだけではなく、列名を左に置き換てくれるんだね。一種の正規化処理といえるのかな。
つまり場合によっては、

WHERE   1 IN (Col1, Col2)

と書いたところで、結局一周周って以下に展開されるというね。

WHERE   (Col1 = 1 OR Col2 =1)

主キーの有無によって展開のされ方が微妙に異なるのは興味深い。因みに Oracle でも確認したところ同様だった。恐らく大抵の DB で同じと思われ。
May the Force be with you.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0