【SQL】SQLにおける条件分岐とは
前回の続きで第三章の主要点をまとめていきたいと思います。 (具体的なテーブル表など割愛させてもらうことが多いです)
今回は、「条件分岐について」です。
少しSQLが書けるようになるとパフォーマンスの考慮が気になってしまいます。 なにか条件があるとUNIONをすぐ使用して、「ほんとにUNIONでいいのかな?」など疑問が湧いてくることがあるかと思います。
思考が組み立てやすいので多用することは仕方のないことですが、パフォーマンスに欠点を抱えてしまうことはありがちです。
こうしたとき、実行計画を気にかけてみるようにしました。 実際には内部的に複数回のSELECT文を実行してしまっている!とか気づきがあるかもしれません。
例えばこのようなSQLがあったとします。 (ネーミングセンスがありません...w)
SELECT name, year FROM People WHERE year <= 1990 UNION ALL SELECT name, year FROM People WHERE year >= 1991;
このSQLだとPeopleテーブルに対して2度のアクセスを実行しています。 フルスキャン実行され読み取りコストが大幅に上がります。 キャッシュに保持されることも想定されますが、大抵テーブルサイズが大きくなるほどキャッシュヒット率は悪くなります。
そしたらどうしたらいいのでしょうか?
SELECT句で条件分岐をする
SELECT name, year, CASE WHEN year <= 1990 THEN 'オールド' WHEN year >= 1991 THEN 'ヤング' FROM People;
このSQLは先程のSQLと同じ結果が出力されます。 が、こちらのほうがパフォーマンスは数段良いです。
UNIONによる分岐は、SELECT文の単位で分岐させています。 CASEによる分岐は、式の単位で分岐させています。(こちらがベター)
SQLを書く時、「IFを使えるのではないか?」と自答してみましょう。 そして使えるのであればCASE式を使えると覚えておきましょう。
それでもUNIONを使用するケースとは
シンプルに言うと、「マージされるSELECT文同士で使用するテーブルが異なる場合」です。
このようなSQLです。
SELECT co_1 FROM Table_A WHERE col_2 = 'a' UNION ALL SELECT co_3 FROM Table_B WHERE col_4 = 'b';
また、場合によっては「複数のインデックススキャン対1回のフルスキャン」が考えられます。
これに関しては、テーブルのサイズが大きくUNIONを使用してWHERE条件の選択率が十分に小さい場合はUNIONが良いでしょう。
まとめ
もともとUNIONは条件分岐を行うために導入されたものではないこと。 プログラミング言語を扱う際は、「文」に思考がまわります。SQLの場合は、「式」であることを頭に入れておきましょう。 できるだけストレージへのI/Oを減らせるかが重要です。
- 前回の記事
- 第一章