Look-ahead Predicate Generation (ルック・アヘッド述部作成)

V5R3 から Look-ahead Predicate Generation という機能がサポートされるようになりました。
一言で強引に言ってしまうと、小さなテーブルの選択条件を元に大きなテーブルを検索するような場合に威力を発揮する機能です。BI (Business Intelligence) に対応した機能、でもあるんでしょうね。

インフォメーション・センターだと「ルック・アヘッド述部生成」に記述があります。
その他、The Power and Magic of LPG という記事があって、こっちの方がだいぶわかりやすく書いてあります。

上記の記事をちょっと敷衍してみましょう。
たとえば以下のように大きいテーブルと小さなテーブルを結合している SQL があるとします。

SELECT * FROM LARGE, SMALL
WHERE LARGE.KEY = SMALL.KEY
AND SMALL..FIELD1 IN (1, 10)

これをそのまま実行させると、極端な場合、LARGE テーブルを全件読み込んで、その度に SMALL テーブルの選択条件をチェックする、というかんじになってしまいます。
このロジックだとどうしても、大きなテーブルを全件読み込んで毎回選択条件に合致するかどうかを結合テーブルに対してテストするわけですから、ディスクへの I/O が多くなってしまいます。

ディスクの I/O というものはメモリーからの読み出しに比較すると、とんでもなく時間のかかるもので、とにかくそれは最小限にする、というのがデータベースのパフォーマンスチューニングについては否定すべくもない第一歩なわけですね。
とにかくディスク I/O を避ける、最小化するためにはどうしたらいいか、を考えるのがオプティマイザーのお仕事、ということになります。

たとえば、こうした場合によくあるオプティマイザーのトリックとしては、

といったことが行われます。

どっちみち LARGE テーブルに対して全件スキャンが行われてしまうのですが、いちいちテストするわけではないのでブロック化した I/O などが使えます。

ただ、よく考えてみると、いくら大きなテーブルとは言え、結局選択されるものは SMALL テーブルの FIELD1 に相当する KEY の値のものだけになります。
それなら初めから SMALL テーブルの選択ずみの行 (レコード) から KEY の値を持ってきて、それを LARGE テーブルの KEY フィールドに対して選択条件として指定してしまっておけばいいわけですね。
つまり、こんな SELECT 文に書き換えられるイメージです。

SELECT * FROM LARGE, SMALL
WHERE LARGE.KEY = SMALL.KEY
AND SMALL..FIELD1 IN (1, 10)
AND LARGE.KEY IN (small.key of 1, small.key of 10)

この SQL を書き換える機能を Look-ahead Predicate Generation (LPG) と読んでいます。
先を読んで SQL の述部を生成するわけですね。

こういうことが、これを適応できるとこをは判断できるような賢いオプティマイザーや、速い CPU、進んだ並行処理のおかげで V5R3 から行うことができるようになっているわけです。こんな機能、他の RDB にはないものですよ。DB2/400 のデータベースとしての優秀性がこんなところからもわかるんじゃないでしょうか。

もちろん、データベースだけが賢いだけではだめですよね。
SMALL テーブルが十分セレクティビティが高い (最終的に選択されて出てくる行が少ない) 状態であり、それがオプティマイザーに知らされていないとわかりません。そのため、カラム統計が重要になってくるわけです。DB2/400 は必要なカラム統計は自動的に取ってくれるから基本的には大丈夫ですが、事前にわかっていて、更新でデータの分布が頻繁に変わってしまうようなカラムが対象の場合はユーザー起動で更新しておいた方がいいでしょう。

結合するファイルが増えれば、それだけ、もともと読まなくてはいけない件数と、この機能によって絞られた件数の差は大きくなるのがわかりますよね。それだけ威力が発揮される、ということになります。

これはオプティマイザーが利用できる戦略がひとつ増えた、ということです。毎回、こうすれば使える、とかそういったものではありません。
きちんとインデックス、カラム統計がある状態で、オプティマイザーがある戦略 (アクセス・プラン) を選択する/しない、というのはそれなりに実効性があることです。オプティマイザーを疑うよりはまず、そういった判断させるための材料が揃っているか、SQL は適切か、といったことを考えましょう。


こちらで紹介した自習用資料からの SQL を使って実験してみました。

ITEM_FACT は10万件、SUPP_DIM は1000件。どちらにも、ひとつもインデックスは作成されておらず、統計も取られていない状態です。
ちなみに、以前紹介した統計マネージャーの機能によって、Visual Explain を実行した状態で、もう結合カラムや選択カラムの統計は取られている状態になります。(ただし、バックグラウンドのジョブで並行して、しかも低優先順位で行われるので完全なものではない場合もあります) そのため、統計のデータはある程度は使われているような気もします。

SELECT year, month, supplier, orderkey, quantity, revenue_wo_tax
FROM item_fact i, supp_dim s
WHERE i.suppkey = s.suppkey
AND quantity = 2
AND supplier = 'Supplier#000000010'
ORDER BY year, month, orderkey;

V5R2 での Visual Explain の実行結果はこちらです。
上で述べた「よくあるオプティマイザーのトリック」が使われているのがわかります。

V5R3 での実行結果はこちらです。
緑色にハイライトされているのは、メニューから「HIGHLIGHT LPG」をチェックしているからです。この部分に LPG が使われているわけです。

「HIGHLIGHT LPG」は Visual Explain の「表示」メニューからチェックできます。

どうすればわかるか、というのはあまり簡単にはわかりにくいのですが、「ステートメント・テキスト」をよく読むと「NODE_97」の結果から SUPPKEY の一致するものをすでにこのテーブル・スキャンの時点で選択するようになっていることがわかります。

こちらの「計画ステップ名」が「NODE_97」になっていますね。

SUPPLIER カラムの統計データを見ると 'Supplier#000000010' はセレクティビティの高い (1件しかない) カラムであることがわかりますね。(全部の関連する統計はこちらにあります)

一時ハッシュ・テーブルの内容がそのまま LPG が使われているテーブルスキャンの「ステートメント・テキスト」の一部になっていることがここで確認できます。

ちなみに V5R2 でも一時ハッシュ・テーブルが使用されていますが、出てくる情報が違います。
「カーディナリティ」といった情報がないことから CQE が使われていることがわかりますね。

[Top Pageに戻る]

Ads by TOK2