DB2 For i のインライン表関数
DB2 for i 7.2 TR4 および IBM i 7.3 で、IBM は、大々的にお話ししなければならない特別なユーザー定義表関数 (UDTF) の機能拡張を行いました。この機能拡張は、インライン表関数と呼ばれます。
Get_Customer_Orders というこの UDTF の簡単な例を考えてみましょう。
関数を起動するときに DB2 は何をするでしょうか。DB2 for i の旧バージョンでは、Visual Explain 内で以下の照会を確認する場合、以下のようになります。
この場合、図 1 に示すような結果になります。
図でおわかりのように、表関数はアクセス・プラン内の単一ステップの「ブラックボックス」として表示され、表関数から唯一行カウント見積りするのは、関数のカーディナリティです。上記の場合、この見積りはデフォルトで 1,000 行です。このプランでは、どのような表または索引が、 UDTF で使用されているか示していません。 現在、DB2 for i の最新バージョンに移行して同じシンプルな照会を実行すると、Visual Explain には以下のように表示されます。
アクセス・プラン同士違うのはなぜでしょうか。答えは DB2 が表関数を「インライン」したためです。プランに示す索引プローブは、SalesOrderHeader 表上の索引向けです。つまり、照会内のビュー参照が DB2 によってアクセス・プランに「展開」されるのと同様に、DB2 は UDTF の表およびロジックを親照会のアクセス・プランに組み込むことができるということです。
これは素晴らしいニュースです。DB2 はアクセス・プランを構築するときに UDTF のリソースを十分に制御できるためです。
図解して、Get_Customer_Orders UDTF をホストするこの照会を考えてみましょう。
Visual Explain が図 3 で示すように、UDTF のアクセス・プランはアクセス・プラン全体に直接組み込まれています。
2 つの索引プローブ演算子が、図 3 に示すプランに組み込まれています。上の演算子は SalesOrderHeader 表で見積り 12 行が戻されています。下の演算子は SalesOrderHeader 表で、ヘッダー当たり見積り 4 行の詳細行が戻されています。
わかりやすくするために、新しいインライン機能以前は、上記照会のプランはどのように見えるかを図 4 に示します。
図 3 と比較した場合の、図 4 のプランで指定された行カウント見積りに注目してください。インライン機能 (図 4) 前は、DB2 は最終照会を見積もると結果的に約 4,000 行になります (表関数の 1,000 行掛けるオーダー・ヘッダー当たり 4 行の詳細行の平均)。インライン機能を使用すると (図 3)、UDTF のリソースが組み込まれるため、DB2 の見積りは 22 行に向上します。指定の定数値でクエリーにより戻される実際の行カウントは 109 行です。
インライン機能のメリットは、 DB2 が直接 UDTF の表を検査して、その行カウントを見積ることです。DB2 にとって行カウントは重要です。そのカウントを利用して、表結合の順序、クエリーが使用する際に割り振るメモリーの見積量などを判断するためです。これらの数字が一致しない場合、DB2 は次善のプランを生成することができます。
もちろん、このささいな例はちょっと他から借りました。カーディナリティ (見積行カウントなど) は、戻されている行数を DB2 がよく理解できるように、表関数定義とともに提供されていたはずです。関数作成時に CARDINALITY 50 を指定していれば、2 つのプラン間の行カウントの莫大な食い違いは処理されていたでしょう。たとえそうでも、パラメーターが大きく変動している複雑な照会では、開発者が、「フリーサイズの」カーディナリティを正確に見積もることは簡単ではありません。そのためインライン機能で DB2 は、表の統計情報を使用して、この行カウント見積りを行います。
さらに、SQL ステートメントで指定した順序にこだわらず、DB2 は照会を再書き込みして、ステートメントの JOIN を最適と思われる順序で実施できる点を思い出してください。ほとんどの場合、DB2 の選択した結合順は、特に複雑な照会では開発者が提供する順序より優れています。過去に UDTF で生成された結果セットが、結合順に関して DB2 で独立型表と見なされていました。しかし、現在はインライン UDTF の表が DB2 に対してオープンであるため、すべての表の結合順を最適化できるよう、ホスト照会の表とともに、 UDTF 内の表を考慮したプランを構築できます。DB2 はビューに対してこれと同じメリットを提供します。ビューの被参照表は、DB2 がすべての表を一度に考慮できるようアクセス・プランに直接組み込まれます。
インラインできる UDTF を作成する場合、いくつかのルールに従う必要があります。インライン機能を使用できる主な要件は、以下のとおりです。
- クエリーは SQE と互換性がなければならない。
- NO EXTERNAL ACTION が必要。
- 別のサーバーのデータを参照しない (リレーショナル・データベース間を参照しないなど)。
- XML は戻されたデータ型ではない。
- 関数に入力パラメーターを使用する共通表式が含まれていない。
- 表関数のルーチン本体は単一の RETURN ステートメントで構成されている。(申し訳ありませんが、複数のステートメントは指定できません。)
- 関数のユーザー・プロファイル (*USER/*OWNER) は親照会と同じでなければならない。
UDTF を作成したら、SYSFUNCS カタログの INLINE 列をチェックしてインラインできるかどうか判断することができます。
関数の INLINE 属性は、親照会にインラインできることのみを示しています。UDTF を参照する照会のランタイム状況に応じて、DB2 はインラインしないように選択できます。(例えば、ホスト照会のユーザー・プロファイルが *USER 下で動作していながら、UDTF が *OWNER で定義されている場合など。)
自分の関数を「インライン」させる
表関数をインラインする DB2 for i の機能は優れた機能です。新たにコーディングの知識も必要なく、いくつかのルールだけでインライン機能を有効にできるかどうか理解できます。一体化したメリットとしては、再利用可能なパラメーター化した関数を作成しながら、関数のロジックと表を、照会プラン全体に組み込む際の DB2 の選択の幅が広がることです。結果としてさらに優れたアクセス・プランになり、効率アップにつながります。