SQL実践入門第5章を読んだ
ループ依存症
問題を細かく分割し、レコードという単位にまで落とし込んだ後に、1レコードに対する処理を繰り返すことで問題を解こうとする心理的態度のこと
ループ依存症のコード
- カード明細を表示するために1行ずつ明細にアクセスするSELECT文をループさせる
- バッチ処理で大量データを処理するため、1行ずつレコードをフェッチしてホスト言語側で処理を行い、また1行ずつテーブルを更新する(めちゃくちゃやったことあるわ...非同期の実装だったから問題なかったか?)
SQLは意図的にループを追放している
ループ依存症のSQLのデメリット
パフォーマンスが悪い
並列分散がやりにくい
データベースの進化による恩恵を受けられない
ループ依存症のSQLのメリット
SQL文が単純極まりないため実行計画もまた単純なものになる。そのために3つのメリットが生まれる
実行計画が安定する
- オプティマイザには使うインデックスを変えるくらいの自由しか許されていないので、本番運用中に実行計画が変わってスローダウンするというトラブルからほぼ自由になれる
処理時間の見積もり精度が(相対的には)高い
トランザクション制御が容易
- 特定のループ回数ごとにコミット処理を行うなど、トランザクションの粒度を細かく設定することができる
ループ依存症のSQLを速くする方法はあるか
複数行を1度に処理するSQLに変える
- 即アプリケーション改修を意味する...
個々のSQLを速くする
- ただし、ループ依存症SQLはもうすでに十分単純なため、改善箇所がない場合も
処理を多重化する
- 最も望みのある選択肢
- CPUやディスクといったリソースに余裕が当て、処理をうまく分割できるキーがあれば、ループそのものを多重化することによってパフォーマンスを線形に近い形でスケールさせられる可能性あり
- 物理リソースがすでにいっぱいいっぱいだとこの方法は採用できない
ループ依存症SQLはチューニングポテンシャルに乏しい
- トレードオフを考えて、ループ依存症のSQLと複数行を一度に処理するSQLのどちらを採用するか判断する必要がある
SQLでループをどう表現するか
CASE式とウィンドウ関数を使おう