そういえば幕張でトラブルに居合わせたんですが。
なんかテスト環境で SQL の結果件数を確認する必要があるとかで、こんな SQL 投げてました。
SELECT COUNT(emp_id)
FROM MonthlyWorktime A
WHERE work_time = (SELECT MAX(work_time) FROM MonthlyWorktime WHERE emp_id = A.emp_id)
(実際にはテーブル名とか違いますが、まぁこんなノリだと思ってください)
この SQL が 1 時間とか経っても終わらないらしく。
ここで MonthlyWorktime のテーブル件数は 7 万件程度。
ざっと考えると(work_time にインデックスは張れないので)テーブル全件検索が 2 回行われている状態のはずで。
14 万件程度の検索で 1 時間もかかるわけがありません。
んー・・・もしかして、DB2 のオプティマイザって頭悪い?
ということで、試しに代替の SQL を投げてもらいました。
SELECT COUNT(A.emp_id)
FROM MonthlyWorktime A,
(SELECT emp_id, MAX(work_time) AS max_work_time FROM MonthlyWorktime GROUP BY emp_id) AS B
WHERE A.emp_id = B.emp_id
AND A.work_time = B.max_work_time
まぁやってることは同じなんですが、これだと一瞬で終わりました。
前者の SQL だと 7 万件検索して、その結果に対してそれぞれ副問合わせやってたってこと?
まぁ 49 億件も検索するならある程度遅くてもわかるような気も。
んー・・・それにしても Oracle や SQLServer だと、どっちの SQL でも同じアクセスプランができそうなもので。
「DB2 のオプティマイザは頭悪いので、開発者側でもある程度効率的な SQL を書きましょう」ってこと?
とか思ってたんですが、よくよく聞いてみると前者の SQL は本番環境でも毎晩実行されているそうで。
本番のデータはテスト環境よりも遥かに多いはずだから、この調子だと一晩で終わらないような・・・
というところでやっと気づきました。
そういえば本番環境は毎日統計情報を更新しているんでした。
一方テスト環境は統計情報を更新してないので、アクセスプランが最適化されていなかったと。
統計情報の更新とか、どうも見落としがちだけど気をつけないといけないなー、と思いました。
ちょうど見かけた記事にもリンク張っておこう。
@IT:RDBMSアーキテクチャの深層(2) Page 2
2005/03/22 よく見ると SQL 間違ってたので修正。
あとテーブル名が Montyly とかなってたのでそこも修正。なぜ気づかないのか謎。