レコードの削除や挿入を繰り返すテーブルは、テーブルの再構築(リビルド)をしないとテーブルのファイルサイズが肥大化したり、集計速度が低下してしまうことがあります。
テーブルの再構築は時間がかかることが多いため、毎日再構築をしてしまっては夜間連携に間に合わない可能性も出てきます。
そこで今回はそのテーブルが再構築が必要かを判定し、必要なテーブルのみ再構築をする処理を紹介します。
運用中のDr.Sumのテーブル数が多い場合や、レコード件数が多い場合などに役立つので、ぜひご覧ください。
テーブルの再構築(リビルド)が必要なタイミングは?
再構築は以下の2種類があります。
リビルドの種類 |
処理内容 |
完全リビルド |
不要領域を削除してインデックスを再配置する。CRXとDATファイルが小さくなる |
簡易リビルド |
不要領域を削除する。DATファイルが小さくなる。 |
マニュアルを引用すると
-
完全リビルドの必要性を確認する
[最大NID]と[カーディナリティ]に注目します。[カーディナリティ]は、[カラムデータ情報]でカラムを選択して[カラムのデータ情報表示]ボタンをクリックすると取得できます。
[カーディナリティ]は有効な行から算出した値であるのに対して、[最大NID]は削除された行も含んだ値です。[カーディナリティ]と[最大NID]に大差がある場合、レコードの追加、削除、変更によるカーディナリティの増減によって、CRXファイルの不要領域が多くなっている可能性があります。完全リビルドの実施を検討してください。
また、NIDは2,147,418,112が上限値です。2,147,418,112に達する前に完全リビルドが必要です。
-
簡易リビルドの必要性を確認する
[件数]と[最大ROWID]に注目します。
[件数]はテーブルの有効な行数であるのに対して、[最大ROWID]は削除された行も含んだ値です。[件数]と[最大ROWID]に大差がある場合、レコードの追加、削除の繰り返しによって、DATファイルの不要領域が多くなっている可能性があります。簡易リビルドの実施を検討してください。
また、ROWIDは2,147,418,112が上限値です。2,147,418,112に達する前に簡易リビルドが必要です。
とあります。
NIDが約20億件に達する前に完全リビルドが必要ですし、ROWIDが約20億件に達する前に簡易リビルドが必要になります。
Enterprise Managerを開き、手動で確認することもできますが、定期的にチェックするのも大変です。
それではDS Scriptを用いて、自動で再構築が必要であるかを判断してみましょう。
ROWIDが19億件以上だったら簡易リビルドを実施する
SET() {
// 再構築するROWIDのしきい値
$CONST_ROWID_THRESHOLD = 1900000000;
// データベース名(引数が未指定の場合の値を指定)
$VAR_DB_NAME := "SALES";
// テーブル名(引数が未指定の場合の値を指定)
$VAR_TABLE_NAME := "受注データ";
}
CONNECT($VAR_DB_NAME) {
}
SET_FROM_QUERY() {
// 最大ROWIDを取得する
$VAR_MAX_ROWID = SELECT MAX(ROWID) FROM ${VAR_TABLE_NAME};
}
PRINT() {
CONCAT($VAR_TABLE_NAME, " MAXIMUM ROWID: ", $VAR_MAX_ROWID);
}
CASE {
WHEN ($VAR_MAX_ROWID >= $CONST_ROWID_THRESHOLD) {
// 最大ROWIDがしきい値を超えたら実行する
PRINT() {
"START COMPACTION TABLE"
}
SQL($_SQL_AUTO_COMMIT_OFF) {
// 簡易リビルドをSQLで実行する
COMPACTION TABLE ${VAR_TABLE_NAME};
}
}
ELSE {
}
}
実際のサンプルプログラムはこちらからダウンロードできます。
こちらは該当のテーブルの最大ROWIDが19億件を超えていたら、そのテーブルに簡易リビルドを実施するものです。
では次に完全リビルドを実施する場合を確認しましょう。
断片率が50%以上だったら完全リビルドを実施する
SET() {
// 再構築する断片率
$CONST_FRAGMENTATION_THRESHOLD = 50;
// データベース名(引数が未指定の場合の値を指定)
$VAR_DB_NAME := "SALES";
// テーブル名(引数が未指定の場合の値を指定)
$VAR_TABLE_NAME := "受注データ";
}
CONNECT($VAR_DB_NAME) {
}
SET_FROM_QUERY() {
// 最大ROWIDと件数から断片率を計算する
$VAR_FRAGMENTATION_RATE = SELECT 100 - TRUNC(COUNT(*) / MAX(ROWID) * 100) FROM ${VAR_TABLE_NAME};
}
PRINT() {
CONCAT($VAR_TABLE_NAME, " FRAGMENTATION RATE: ", $VAR_FRAGMENTATION_RATE);
}
CASE {
WHEN ($VAR_FRAGMENTATION_RATE >= $CONST_FRAGMENTATION_THRESHOLD) {
// 断片率がしきい値以上だったら実行する
PRINT() {
"START REBUILD TABLE"
}
SQL($_SQL_AUTO_COMMIT_OFF) {
// 完全リビルドをSQLで実行する
REBUILD TABLE ${VAR_TABLE_NAME};
}
}
ELSE {
}
}
実際のサンプルプログラムはこちらからダウンロードできます。
こちらは該当のテーブルの断片率(最大ROWIDと現在のテーブル件数から算出)が50%以上であれば完全リビルドを実行します。
これで定期的にテーブルの状況が確認できますね。
データベース内のテーブルの断片率をチェックして50%以上なら完全リビルドをする
先程は1つのテーブルを指定する断片率チェックでしたが、今回はデータベース内のテーブルをすべてにチェックをかけるスクリプトです。
SET() {
// 再構築する断片率
$CONST_FRAGMENTATION_THRESHOLD = 50;
// データベース名(引数が未指定の場合の値を指定)
$VAR_DB_NAME := "SALES";
}
SESSION_CONNECT ($VAR_DB_NAME) {
SET_CURSOR() {
// システムテーブルからテーブルリストを取得する
@VAR_ALL_TABLES(name) = SELECT table_name FROM __all_tables__ WHERE assortment='table';
}
FOREACH (@VAR_ALL_TABLES) {
SET_FROM_QUERY() {
// 最大ROWIDと件数から断片率を計算する
$VAR_FRAGMENTATION_RATE = SELECT 100 - TRUNC(NVL(COUNT(*) / MAX(ROWID), 1) * 100) FROM ${VAR_ALL_TABLES_name};
}
PRINT() {
CONCAT($VAR_ALL_TABLES_name, " FRAGMENTATION RATE: ", $VAR_FRAGMENTATION_RATE);
}
CASE {
WHEN ($VAR_FRAGMENTATION_RATE >= $CONST_FRAGMENTATION_THRESHOLD) {
// 断片率がしきい値以上だったら実行する
PRINT() {
"START REBUILD TABLE"
}
SQL($_SQL_AUTO_COMMIT_OFF) {
// 完全リビルドをSQLで実行する
REBUILD TABLE ${VAR_ALL_TABLES_name};
}
}
ELSE {
}
}
}
}
冒頭のSET文の中のデータベース名を任意のものに変換します。
これで必要なテーブルのみの完全リビルドができますので、メンテナンスにかかる時間が少なくなりますね。
ダウンロードしたdhnファイルを自社の環境に適用する方法
dhnファイルをダウンロードしたら、ファイルを開いて5行目と7行目のデータベース名とテーブル名を自社の環境のデータベースとテーブルに変更します。
そしてScript Editorを開き、左下のスクリプトファイルを右クリックし[アップロード]から該当のdhnファイルを取り込みます。
[実行]をしてみて、エラーが出ないことを確認したら、dhnファイルを保存しましょう。
これで自社環境でサンプルスクリプトを使用することができます。
DS Scriptをバッチから呼び出して自動化しよう
バッチでdhnファイルを呼び出し、DS Scriptを動かしましょう。
DS Scriptのバッチからの起動方法についてはこちらの記事を参照してください。
日々のメンテナンスをしっかり行うことで、Dr.Sumは最高のパフォーマンスで活躍します。
日々のメンテナンスも自動化できるところをしっかりと検討し、効率的にDr.Sumの最高のパフォーマンスを維持するようにしましょう。