「SQLアンチパターン」を読んで【第Ⅲ部】

書籍

SQLアンチパターン

SQLアンチパターン

はじめに

読んだ書籍は1記事にまとめると文量が多くなるため、導入+各部ごとの記事としてまとめる。

本記事は「第Ⅲ部:クエリのアンチパターン」になる。その他の部についての記事は下記参照。

印象に残った点

※ 下記のカッコ書きは該当する章番号。

フィア・オブ・ジ・アンノウン(恐怖のunknown)[13]

- 目的:欠けている値を区別する
- アンチパターン:NULLを一般値として使う、または一般値をNULLとして使う
- アンチパターンを用いてもよい場合
  - 外部データの入出力
  - 欠けている値の区別
- 解決策:NULLを一意な値として使う
  • SQLの3値論理の振る舞いを理解していれば迷うことはない。ただ3値理論だと知らなかったらハマるのは分かる。
  • IS DISTINCT FROM便利だなぁ。対応していない製品もあるのか。

アンビギュアスグループ(曖昧なグループ)[14]

- 目的:グループ内で最大値を持つ行を取得する
- アンチパターン:非グループ化列を参照する
- アンチパターンを用いてもよい場合
  - 関数従属性を用いてクエリ結果の曖昧性をなくせる場合
- 解決策:曖昧でない列を使用する
  - 関数従属性のある列のみにクエリを実行する
  - 相関サブクエリを使用する
  - 導出テーブルを使用する
  - 他の列に対しても集約関数を使用する
  • 単一値の原則か。普段利用しているDBMSだとエラーが出るためあまり意識していなかった。違う製品使っていたら危なかったかも。

ランダムセレクション[15]

- 目的:サンプル行をフェッチする
- アンチパターン:データをランダムにソートする
- アンチパターンを用いてもよい場合
  - データセットが小さく、大きくなる増える可能性もない場合
- 解決策:特定の順番に依存しない
  - ランダムなキー値を選択する
  - アプリケーションコードで対応する
  - ベンダー依存の解決策を使う
  • ランダムな値を業務上使う事がなかったのでなるほど。と思うところが多かった。インデックスが効くかどうかを常に意識することが鍵だなぁ。
  • ベンダー依存の解決策は製品間の移行を考えなければ良い解決策だと感じた。

プアマンズ・サーチエンジン(貧者のサーチエンジン)[16]

- 目的:全文検索を行う
- アンチパターン:パターンマッチ述語を使用する
- アンチパターンを用いてもよい場合
  - シンプルな用途や使用頻度が低い場合
- 解決策:適切なツールを使用する
  - ベンダー拡張機能を使用する
  - サードパーティのサーチエンジンを使用する
  - 転置インデックスを自作する

スパゲッティクエリ[17]

- 目的:SQLクエリの数を減らす
- アンチパターン:複雑な問題をワンステップで解決しようとする
  - デカルト積が発生し想定外の結果になる場合がある
- アンチパターンを用いてもよい場合
  - 単一SQLクエリを前提とするコンポーネントやレポートツールを利用している場合
  - 複数の結果を1つのソート順で表示させたい場合
- 解決策:分割統治を行う
  - ワンステップずつ
  - UNIONを使う
  - SQLを用いてSQLの自動記述する
  • 複雑なSQLをメンテするのは本当に辛いので分割統治は保守観点からみてもとてもありがたい。
  • SQLの結果にSQL文を出力させるのか。そういう考えはなかった!実務でも使えそう!
  • デカルト積とは何ぞや?と思ったが、結合のベースとなる考えとのこと。
    • 抽出条件によって制限をかけないとデカルト積になるのか。なるほど。(参考)

インプリシットカラム(暗黙の列)[18]

- 目的:タイプ数を減らす
- アンチパターン:ショートカットの罠に陥る
  - ワイルドカードや暗黙的な列指定によってタイプ数を減らすも、リファクタリングや帯域の使いすぎになる
- アンチパターンを用いてもよい場合
  - アドホックなSQL
  - 開発時の効率や可読性の向上をトレードオフしてでも採用したい場合
- 解決策:列名を明示的に指定する
  • ワイルドカードを使うクエリの代償は考えてなかった。誤りの防止やスループットの抑制のためにも明示したほうが良い。
  • ワイルドカードの例を袋の飴(袋に入った飴を買っても飴を食べるときは最終的には取り出さないといけない)に例えており、秀逸だなぁーと感じた。全くもってその通り。