DB2 データベースのいくつかのクエリの最適化に取り組んでいます。それらのほとんどは正常に動作していますが、返されるデータセットがかなり大きいもの (最大 30k 行程度) がいくつかあり、問題が発生しています。これらのクエリについて、それほど複雑なことはありません。内部結合と左結合を含む、最大で約 12 の結合からおそらく 15 の異なる列を選択します。パラメータとサブクエリを使用してデータセットを削減するいくつかの IN 句があります。それは特別なことではありません。
私はいくつかのインデックスを見てきましたが、あまり運がありませんでした。問題は、使用されていない新しいインデックスの使用を強制しようとしたときに、DB2 で気の利いたトリックに出くわしたことです: コストと実行時間を潜在的に削減できる、述部の no-op COALESCE です。
基本的には、次のように機能します。
SELECT ...
FROM A
JOIN B
ON A.ID1 = B.ID1
AND A.ID2 = B.ID2
--More inner and left joins--
WHERE
B.TYPE_CODE IN (:parameter)
AND A.X IN (--subquery--)
AND
COALESCE(B.TYPE_CODE,B.TYPE_CODE) = B.TYPE_CODE
COALESCE は論理的な観点からは何もせず、B.TYPE_CODE が null になることはありません。ただし、これにより、DB2 オプティマイザーはより少ない数の行を見積もるようになります。説明は次のとおりです。
http://www-01.ibm.com/support/docview.wss?uid=swg21259831
表 B については、TYPE_CODE 列には約 15 の異なる値があり、分布は均一ではありません。そこには約 270 万行、A には約 90 万行あります。そのため、B の ID1/ID2 列は、同じ値のペアを最大 15 回繰り返すか、1 回だけ発生する可能性があります。: パラメータは 4 つ以下の値です。
奇妙なことに、COALESCE ステートメントによってクエリ時間が半分に短縮されます。EXPLAIN PLAN を確認したところ、A でのいくつかのテーブル スキャンがインデックス スキャンになっていることに気付きました。これは、返される行の推定値が低く、オプティマイザがインデックス スキャンを実行できるためと考えられます。私は掘り下げて、これについて考えられる理由を見つけようとしています。これらのテーブルで RUNSTATS が実行されたのはごく最近で、SYSCAT.COLDIST テーブルにはかなり最近のデータが含まれており、カウントを手動で確認した場合、少なくとも値の 1% 以内です。TYPE_CODE 列のすべての値が含まれているわけではないことに気付きましたが、欠落している値は非常にまれであり、IN 句からまれな値を省略しても、クエリ時間に実際の影響はありません。他の列で COALESCE を試しましたが、同じ効果はありませんでした。
私が考えることができる唯一の説明は、いくつかの統計が古い、悪い、時代遅れなどであるということですが、この時点でどこを見るべきかを知っていれば、とんでもない. 列グループの統計が適切に配置されていないとは言えますが、それが違いを生むかどうかを言うほどの知識はありません.
COALESCE ステートメントは少しハックであり、それ自体が解決策というよりも、より深い問題に対する応急処置であるため、本番環境に入れたくありません。DB2 は、その結合で返される行数を過大評価しているように思えますが、その理由を知っていれば気が遠くなります。DB2の経験を持つ他の人がこれに光を当てることができるかもしれないと思っていました.