インデックス・アドバイザー

iSeries の DB2/400 には"インデックス・アドバイザー"という機能があります。

DB2/400 がある SQL を実行する際には、どういうプランでそれを実行するのがいいのかを検討する過程があります。(最適化)
SQL 文そのものはリレーショナル代数に変換することができ、それを数学的に変形していく過程であり、ここでどれくらい賢く展開できるか、というのがデータベース・エンジンの性能を決めるわけです。
その際、アクセスされるテーブル/ファイルがどれくらいの行/レコードを持っており、アクセスされるカラム/フィールドがどのような分布の値を持っているか、というような情報、さらにどういうカラム/フィールドについてどのようなインデックスがあるか、という情報をもとにどのプランが最適なのかを決めるわけです。(実際には、こうした内容を元に展開の戦略を決めることもあるわけで、必ずしも実装はこの順番ではないと思いますが)

こうした過程で、こういうインデックスが存在していればもっと効率のいいプランが作れたのに、といった情報はいずれにしても副次的に産出されてしまうわけです。もちろん、それほど賢いデータベース・エンジンであれば、という前提ですが。

DB2/400 はそうした過程で生み出される"こんなインデックスがあればよかったのに"を記録しておいてくれます。
つまり、それがそのまま"アドバイスされるインデックス"なわけですね。

アドバイス情報の表示にはiSeries ナビゲーターからの表示が一般的ですが、内容は QSYS2/SYSIXADV (IASP の場合は QSYS2xxxxx/SYSIXADV の方が実際) というテーブルに格納されているので SQL でのアクセスが可能です。

データベース・モニターなどの場合と違って一つのテーブルにデータがあるので、SQL 自体は簡単です。
たとえば、こんなかんじでしょうか。(IASP の場合は qsys2 のところが QSYS2xxxxx になります)

SELECT SYSTEM_TABLE_NAME, TABLE_SCHEMA, LAST_ADVISED,
TIMES_ADVISED, ESTIMATED_CREATION_TIME, REASON_ADVISED, INDEX_TYPE,
MOST_EXPENSIVE_QUERY, AVERAGE_QUERY_ESTIMATE, TABLE_SIZE, MTI_USED,
MTI_CREATED, LAST_MTI_USED, LEADING_COLUMN_KEYS,
KEY_COLUMNS_ADVISED FROM qsys2/SYSIXADV WHERE
MOST_EXPENSIVE_QUERY > 1 and (MTI_USED > 0 or MTI_CREATED > 0)

↑では一時インデックスを実際に作成し、使用してしまっているものを選択して表示しています。
少なくとも現時点 (V5R4) では、特にインデックスが張られていないようなので ORDER BY を何かに指定するとアクセス・パスの作成をしはじめてしまいます。特に何も指定しない方が結果は早く返ってきますので、あとでコピーしたデータを並べ替えるようにした方がいいかもしれません。

もともとデータベース・モニターなどで生成される情報と同じものが大半ですので、情報に信頼性がない、というようなことはまったくありません。
コード化されているような内容はデータベース・モニター関連の情報を参照する必要があります。

たとえば、REASON_ADVISED というカラムの内容は QQRCOD 理由コードをみています。

ちなみに、これを SQL 文に取り込んでしまうこともできます。
(STRSQL 画面にコピー&ペーストしやすいように幅を狭めています)

SELECT TABLE_NAME, TABLE_SCHEMA, SYSTEM_TABLE_NAME, LAST_ADVISED,
TIMES_ADVISED, ESTIMATED_CREATION_TIME, CASE REASON_ADVISED WHEN
'I1' THEN ' 行選択 ' WHEN 'I2' THEN ' ORDER BY または GROUP BY'
WHEN 'I3' THEN ' 行選択および ORDER BY または GROUP BY' WHEN 'I4'
THEN ' ネスト・ループ結合 ' WHEN 'I5' THEN
' ビットマップ処理を使用した行選択 ' ELSE REASON_ADVISED END AS
"REASON CODE", MOST_EXPENSIVE_QUERY, MTI_USED, MTI_CREATED,
LAST_MTI_USED FROM SYSIXADV WHERE
MOST_EXPENSIVE_QUERY > 1 and (MTI_USED > 0 or MTI_CREATED > 0)

表示方法が異なっているものもあり、INDEX_TYPE というカラムの内容については元になっている QVC1F 推奨索引のタイプ には以下のようになっているのが

たとえば "B" の場合は "RADIX" と表示されるので、WHERE で選択対象にするような場合は注意が必要になりますね。

ちなみにこの SYSIXADV というファイルは自動で削除されたりはしないので、期間と容量などを参考に DELETE する必要があります。
もともとの設計としては、iSeries ナビゲーターで見て、推奨されたインデックスを検討して必要なら作成し、削除する (iSeries ナビゲーターには削除するメニューがあります) というオペレーションを想定してるんだと思いますので、その通りに運用できれば一番いいでしょう。
ただ、せっかくこうやってテーブル・レイアウトが公開されているので、定期的に (内容を見てある閾値を超えたら、でもいいでしょうし、純粋に週次などの定期でも) スケジュールジョブや常駐ジョブなどでリストを出力する/メッセージを出すなどして自動的に管理する、というのもいいのではないでしょうか。

あと、↑の SQL 文でテーブル名とスキーマをまとめてより見やすくするためにこんなふうにすることもできますね。

SELECT                                                               
RTRIM(TABLE_SCHEMA) || '/' || TRIM(T FROM TABLE_NAME) as TABLE,     
SYSTEM_TABLE_NAME, LAST_ADVISED, TIMES_ADVISED,                     
ESTIMATED_CREATION_TIME,                                             
CASE REASON_ADVISED WHEN 'I1' THEN '  行選択  '
 WHEN 'I2' THEN ' ORDER BY  または  GROUP BY  '
 WHEN 'I3' THEN '  行選択および  ORDER BY  または  GROUP BY'
 WHEN 'I4' THEN '  ネスト・ループ結合  '
 WHEN 'I5' THEN '  ビットマップ処理を使用した行選択  '
 ELSE REASON_ADVISED END AS "REASON CODE",
MOST_EXPENSIVE_QUERY, MTI_USED, MTI_CREATED,                         
LAST_MTI_USED                                                       
 FROM SYSIXADV                                                       
 WHERE MOST_EXPENSIVE_QUERY > 1 and (MTI_USED > 0 or MTI_CREATED > 0) 

ちなみに実は RTRIM(TABLE_SCHEMA) とTRIM(T FROM TABLE_NAME) は同じことを意味しています。 参考のためにどちらも書いてみました。
SQL として標準の書き方はTRIM(TRAILING FROM TABLE_NAME) ですね。

[Top Pageに戻る]

Ads by TOK2