ORACLEデータベースの調整

統計情報の収集

STATISTICSオプションを指定したSQLコマンドANALYZEを使用することによって、表・索引・クラスタの物理記憶特性を収集・保存することができる。データディクショナリに保存された統計データは、各種のビューを通じて参照することができる。なお、分析を行うためには、そのオブジェクトを所有しているか、あるいはANALYZE ANYシステム権限が必要である。

ANALYZEコマンド

SQLコマンドANALYZEの統計情報収集のための書式は以下の通りである。

ANALYZE [オブジェクト種類] [オブジェクト名] COMPUTE STATISTICS;

この構文は、指定したオブジェクト全体を走査し、正確な統計を作成する。

ANALYZE [オブジェクト種類] [オブジェクト名] ESTIMATE STATISTICS
   {SAMPLE ([数値] ROWS | [数値] PERCENT)}

この構文は、指定したオブジェクトの一部をサンプリングし、、統計見積もりを作成する。SAMPLEで使用するサンプルの量を件数または百分率で指定できるが、デフォルト値は1064行である。なお、サンプルの量を全体の半分以上に指定した場合は、サンプリングではなく全件走査が行われる。

また、同等の作業を行うプロシージャも定義されている。

DBMS_UTILITY.ANALYZE_SCHEMA([スキーマ名],[作業])
指定したスキーマ内のすべてのオブジェクトの統計を収集する
DBMS_DDL.ANALYZE_OBJECT([オブジェクト種別],[スキーマ名],[オブジェクト名],[作業])
指定したオブジェクトの統計を収集する

なお、統計分析を行うことにより、該当オブジェクトを参照する共有SQL文はメモリからフラッシュされる。

収集できる情報

ANALYZEコマンドによって収集できる情報は以下のようなものである。

種別索引クラスタ
必ず正確な情報 使用ブロック
未使用ブロック
列の最大値
列の最小値
索引レベル
最小キー値
最大キー値
(なし)
見積もり情報 行数
利用可能空き領域
連鎖行数
平均行長
列あたりユニーク値数
リーフ・ブロック数
ユニークキー数
キー当りの平均リーフ・ブロック数
キー当りの平均データ・ブロック数
クラスタ化係数
平均クラスタ・キー連鎖長
使用するビュー (USER|ALL|DBA)_TABLES,
(USER|ALL|DBA)_TAB_COLUMNS
(USER|ALL|DBA)_INDEXES -

SGAの調整

SGAは、特殊な理由が無い場合、常に主メモリー内に保持されることが保証されねばならない。SGAと個々の内部構造への割り当てメモリ量は、Server Manager文SHOW SGAにて確認できる。

ライブラリ・キャッシュの調整

ライブラリ・キャッシュは、SQL文の実行のための解析情報を保存・共有するものである。この利用統計は、動的パフォーマンス表v$librarycacheから得ることができる。

SELECT SUM(pins) "Executions", SUM(reloads) "Cache Misses" FROM v$librarycache;

キャッシュミスの率が1%を超える場合、共有プールサイズにより大きなメモリを割り当てるようにするか(SHARED_POOL_SIZEの値を大きくする)、同一のSQL文を書く(可能なときはバインド変数を使う)ことで、キャッシュミスを減らすようにする。

ライブラリ・キャッシュミスが無い場合、初期化パラメータCURSOR_SPACE_FOR_TIMEをTRUEに指定することにより、アプリケーションが使用中の解析情報をキャッシュアウトしなくなるので、そのための時間がわずかながら節約できる。

データ・ディクショナリ・キャッシュの調整

データ・ディクショナリ・キャッシュは、データ・キャッシュのインデックスの役割を果たす。この利用統計は、動的パフォーマンス表v$rowcacheから得ることができる。

SELECT SUM(gets) "Gets", SUM(getmisses) "Cache Misses" FROM v$rowcache;

キャッシュミスの率が10%〜15%を超える場合、共有プールサイズにより大きなメモリを割り当てるようにする。

マルチスレッド・サーバでの共有プールの調整

マルチスレッド・サーバ構成では、セッションごとのSQL領域やソート領域は共有プール内に格納される。この利用統計は、動的パフォーマンス表v$sesstatから得ることができる。

SELECT name, SUM(value) || 'bytes' "total memory for"
  FROM v$sesstat, v$statname
  WHERE name IN ('session memory','max session memory')
    AND v$sesstat.statistic# = v$statname.statistic#
  GROUP BY name;

ここで得られたメモリ量は、共有プールのサイズを見積もるときの目安となる。

バッファ・キャッシュの調整

バッファ・キャッシュは、メモリ上に持たれるデータベースの最新イメージである。この利用統計は、動的パフォーマンス表v$sysstatから得ることができる。

SELECT name, value
  FROM v$sysstat
  WHERE name IN ('db block gets','consistent gets','physical reads');

この問い合わせから得られる結果を元にして、バッファヒット率を以下のように計算する。

ヒット率 = 1 - ([physical reads] / ([db block gets] + [consistent gets]))

ヒット率が70%を下回るほど小さい場合には、初期化パラメータDB_BLOCK_BUFFERSの値を増やす。

また、ORACLEにはキャッシュ・バッファの利用率を見積もるための仮想表sys.x$kcbrbhが用意されている。これは、キャッシュに追加するバッファ数と、それによって得られるキャッシュ・ヒット数を表示するものである。これを有効にするためには、DB_BLOCK_LRU_EXTENDED_STATISTICSの値を追加を考える最大のバッファ数に設定する。また、初期化パラメータDB_BLOCK_LRU_STATISTICSをTRUEとし、仮想表sys.x$kcbcbhを用いることで、バッファ割り当てを減らした場合の影響を調べることもできる。なお、これらの表には、sysユーザしかアクセスできない。

I/Oの分散

I/O情報の収集

ORACLEによるディスク・アクティビティは、動的パフォーマンス表v$filestatから得ることができる。

SELECT  name, phyrds, phywrts
  FROM  v$filestat fs, v$datafile df
  WHERE df.file# = fs.file#

この問い合わせを何度か行い、その時間間隔も求めて、時間当りのI/O発生率を求める。このI/O発生率が大きい場合(たとえばUNIXならディスク当り40/sec以上)場合は、I/Oの分散を検討する必要がある。

I/Oの分散方法

I/Oの分散方法には以下のようなものがある。

使用中のテーブルに別のデータファイルのエクステントを割り当てるためには、以下のようなコマンドを使用する。

ALTER TABLE [テーブル名]
    ALLOCATE EXTENT ( SIZE [サイズ] DATAFILE [ファイル名]);

SQL文のチューニング

発行するSQL文が、実際にどれだけのCPU時間や物理・論理読み込みを行ったかということは、SQLトレース機能を用いて判別できる。この機能を使用するには、以下の手順を実行する:

  1. 初期化パラメータTIMED_STATISTICS・MAX_DUMP_FILE_SIZE・USER_DUMP_DESTを設定する
  2. ALTER SESSION SET SQL_TRACE = TRUE;コマンドを発行する
  3. トレースファイルをTKPROFコマンドで分析する

また、SQL文がどのように実行されるかということは、EXPLAIN PLAN文で分析する。

行連鎖・行移行の管理

VARCHARデータ型などにより行の長さが不定の場合、UPDATE文が行の長さを変えることにより、行が元のデータブロックに保持できなくなることがある。この場合、その行は別のデータブロックに保存されることになり、それを「行の移行」という。また、行の長さが利用可能なブロックに収まらない場合、その 行は複数のブロックに分割して保存されることになる。これを「行の連鎖」という。

行連鎖・行移行の発見

行連鎖・行移行は、LIST CHAINED ROWSオプションを使用したANALYZE文で調査できる。その利用方法は以下の通り。

  1. UTLCHAIN.SQLスクリプトを使用して、結果を格納するCHAINED_ROWS出力表を作成する。この表はユーザのローカル・データベースに存在する必要がある(逆に通常ユーザが作成できる)
  2. ANALYZE [種別] [オブジェクト名] LIST CHAINED ROWS {INTO (リスト表名)};コマンドを発行して、情報を収集する。
  3. CHAINED_ROWS表を参照して、行連鎖・行移行の状況を出力する。

行連鎖・行移行の処理

行連鎖・行移行が大量にある場合には、以下のプロセスを実行してそれらを取り除く。

  1. 対象のテーブルと同じ構造の作業テーブルを作成する
  2. 連鎖行・移行行を作業テーブルにコピーする
  3. 対象のテーブルから連鎖行・移行行を削除する
  4. 作業テーブルから対象のテーブルに退避していた行をコピーする
  5. 作業テーブルを削除する