SQLer 生島勘富 のブログ

RDB・SQLの話題を中心に情報発信をしています。

実行計画のキャッシュについて1 - 分岐を避けるSQL

かつて文字列連結をして、SQL文を構築していた時代がありました。

現在では ORM を利用することが多いかもしれません。

しかし、論理演算をしっかり理解して工夫すれば SQL だけで WHERE句などを分岐せずに作ることが可能です。

目次

 

 

分岐(IF文)か計算式か

私はプログラマ(設計者)の資質に「言い換えが巧いか」ということを重視しています。

例えば、消費税率が8%で非課税品があったとき、商品マスタの非課税品の税率項目に 0、課税品には 0.08 を登録しておけば、単純な計算で問題ありません。

しかし、慣れていないと日本語で仕様書を書くときに

非課税品フラグが1のときは、消費税を課税しない(消費税をゼロにする) 

 のように書き、これをそのまま分岐(IF文)で処理してしまう人が出てきてしまう。

日本語に限らず、

  • 0を得たいときに、0 を掛ける
  • 変化なしを得たいとき、1 を掛ける(で割る)
  • 変化なしを得たいとき、0 を足す(を引く)

などの処理は、自然言語としては、「暗黙の変換が起きる」

つまり、消費税のように税率が0%と8%があるとすればよいところを、非課税品目と課税品目という風に表現されます。

そのため、「その逆の暗黙の変換」

つまり、非課税品目とは「税率が0%である」と言い換えができるか、というのはIT技術者にとって非常に重要な資質だと考えている訳です。

論理演算について

sikushima.hatenablog.comでも書きましたが、基本的に

  • AND(論理積)は掛け算
  • OR(論理和)は足し算
  • True は 1(0以外)
  • False は 0

と置き換えて考えて問題ありません。

展開、因数分解も数式と同じになります。

例えば数式で、展開した式と、因数分解した式は、

 (a × b) + (a × c)

  = a × (b + c) 

 掛け算を AND 、足し算を OR に置き換えた論理式も同様になります。

(a AND b) OR (a AND c) 

  = a AND (b OR c)           

 日本語の例としては、

男性で日本人、または、男性でアメリカ人

男性で、日本人、または、アメリカ人

日本語に限らず、自然言語(特に日本語は)を因数分解すると、最初の「男性で、」が、どこまでに掛かっているのか分かりにくく間違いのもと(例えば、『牛乳があれば』というジョーク)になりますが、理屈は同じです。

これが、(思考の上、自然言語ソースコード)スラスラできていない人のソースコードは、ネストが深くなり、くどくて非常に読みにくくなってしまいます。

分岐を避けるSQL

もちろん、SQLでも同じで、他の言語と比べるとSQLには分岐がないため、この応用が特に重要になります。

ちゃんと理解していれば、スライドの通り、分岐をしてWHERE句を動的生成する必要はありません。 

f:id:Sikushima:20190410111656p:plain

f:id:Sikushima:20190410111755p:plain

f:id:Sikushima:20190410111837p:plain(……OR NULL IS NULL)

つまり、

(……OR True)

となると、カッコの内側にどんな条件があっても、必ず、Trueになりますから、カラムの内容を確認する必要がない訳です。

f:id:Sikushima:20190410111910p:plain

f:id:Sikushima:20190410111924p:plainf:id:Sikushima:20190410111937p:plain

f:id:Sikushima:20190410111956p:plain

パースが必要(実行計画のキャッシュが使えない)

一つのSQLで複数の実行計画になるということは、実行計画のキャッシュが使えないということになります。

商用サーバでは実行計画をキャッシュしていますので、それが使えないのはいただけないですね。

次回は、実行計画のキャッシュの違いと、提案について書きます。