Oracleの統計情報をロック・削除・移行する方法【DBMS_STATS応用編】

当ページのリンクには広告が含まれています。

Oracleの統計情報収集は基本中の基本ですが、現場では「収集したら逆に遅くなった」「本番と検証で同じ実行計画にしたい」といった場面がよくあります。

この記事では、DBMS_STATS の応用プロシージャを使った以下の操作を解説します。

  • 統計情報のロック(固定化)
  • 統計情報の削除
  • 統計情報のバージョン復元(古い統計情報に戻す)
  • 統計情報の環境間移行(本番→検証)

目次

統計情報のロック(固定化)

なぜロックが必要なのか

夜間の自動統計収集で実行計画が変わって、翌朝から急にSQLが遅くなる──これは現場でよくある「あるある」です。

特定のテーブルの統計情報を固定化しておくと、自動収集・手動収集の対象から外れ、実行計画が安定します。

テーブルの統計情報をロックする

sql

BEGIN
    DBMS_STATS.LOCK_TABLE_STATS(
         OWNNAME  => 'オーナー名'
        ,TABNAME  => 'テーブル名'
    );
END;
/

ロックされているか確認する

sql

SELECT TABLE_NAME, STATTYPE_LOCKED
FROM USER_TAB_STATISTICS
WHERE TABLE_NAME = 'テーブル名'
;

STATTYPE_LOCKEDALL になっていればロックされています。

スキーマ全体をロックする

sql

BEGIN
    DBMS_STATS.LOCK_SCHEMA_STATS(
        OWNNAME => 'オーナー名'
    );
END;
/

ロックを解除する

sql

BEGIN
    DBMS_STATS.UNLOCK_TABLE_STATS(
         OWNNAME  => 'オーナー名'
        ,TABNAME  => 'テーブル名'
    );
END;
/

統計情報の削除

テーブルやインデックスの統計情報を削除(クリア)します。削除後はOracleが動的サンプリングを使用します。

注意: 統計情報を削除すると、オプティマイザがSQLの最初の実行時に動的サンプリングを行うため、初回実行が遅くなることがあります。

テーブルの統計情報を削除する

sql

BEGIN
    DBMS_STATS.DELETE_TABLE_STATS(
         OWNNAME  => 'オーナー名'
        ,TABNAME  => 'テーブル名'
    );
END;
/

インデックスの統計情報を削除する

sql

BEGIN
    DBMS_STATS.DELETE_INDEX_STATS(
         OWNNAME  => 'オーナー名'
        ,INDNAME  => 'インデックス名'
    );
END;
/

スキーマ全体の統計情報を削除する

sql

BEGIN
    DBMS_STATS.DELETE_SCHEMA_STATS(
        OWNNAME => 'オーナー名'
    );
END;
/

統計情報のバージョン復元(以前の統計情報に戻す)

Oracle 10g以降、統計情報は変更前の値が自動的に保存されています(デフォルト保存期間:31日間)。統計収集後に実行計画が悪化した場合、前の統計情報に戻すことができます。

保存されている統計情報の履歴を確認する

sql

SELECT STATS_UPDATE_TIME
FROM DBA_OPTSTAT_OPERATIONS
WHERE OPERATION IN ('gather_table_stats', 'gather_schema_stats')
ORDER BY STATS_UPDATE_TIME DESC
;

特定の時刻の統計情報に戻す

sql

BEGIN
    DBMS_STATS.RESTORE_TABLE_STATS(
         OWNNAME     => 'オーナー名'
        ,TABNAME     => 'テーブル名'
        ,AS_OF_TIMESTAMP => TO_TIMESTAMP('2026-04-01 22:00:00', 'YYYY-MM-DD HH24:MI:SS')
    );
END;
/

スキーマ全体を特定時刻に戻す

sql

BEGIN
    DBMS_STATS.RESTORE_SCHEMA_STATS(
         OWNNAME     => 'オーナー名'
        ,AS_OF_TIMESTAMP => TO_TIMESTAMP('2026-04-01 22:00:00', 'YYYY-MM-DD HH24:MI:SS')
    );
END;
/

統計情報の保存期間を変更する(デフォルト31日)

sql

-- 60日間に変更する例
BEGIN
    DBMS_STATS.ALTER_STATS_HISTORY_RETENTION(60);
END;
/

-- 現在の保存期間を確認する
SELECT DBMS_STATS.GET_STATS_HISTORY_RETENTION FROM DUAL;

統計情報の環境間移行(本番→検証への移行)

本番環境の統計情報を検証環境にコピーすることで、検証環境でも本番と同じ実行計画を再現できます。

手順の概要

本番環境 ──エクスポート──► stattab(中間テーブル)──インポート──► 検証環境

手順1:中間テーブル(stattab)を作成する

本番・検証の両環境に統計情報格納用のテーブルを作成します。

sql

BEGIN
    DBMS_STATS.CREATE_STAT_TABLE(
         OWNNAME  => 'オーナー名'
        ,STATTAB  => 'STATS_WORK'    -- 任意のテーブル名
    );
END;
/

手順2:本番環境の統計情報をstattabにエクスポートする

sql

BEGIN
    DBMS_STATS.EXPORT_TABLE_STATS(
         OWNNAME  => 'オーナー名'
        ,TABNAME  => 'テーブル名'
        ,STATTAB  => 'STATS_WORK'
    );
END;
/

手順3:stattabを検証環境に転送する

Data PumpやDB Linkなどでstattabのデータを検証環境にコピーします。

sql

-- DB Linkを使う場合の例(本番→検証方向に接続できる場合)
INSERT INTO STATS_WORK
SELECT * FROM STATS_WORK@本番のDBリンク名;
COMMIT;

手順4:検証環境にインポートする

sql

BEGIN
    DBMS_STATS.IMPORT_TABLE_STATS(
         OWNNAME  => 'オーナー名'
        ,TABNAME  => 'テーブル名'
        ,STATTAB  => 'STATS_WORK'
    );
END;
/

主要プロシージャ一覧まとめ

プロシージャ機能
LOCK_TABLE_STATSテーブル統計情報をロック(固定化)
LOCK_SCHEMA_STATSスキーマ全体をロック
UNLOCK_TABLE_STATSテーブル統計情報のロック解除
DELETE_TABLE_STATSテーブル統計情報を削除
DELETE_SCHEMA_STATSスキーマ全体の統計情報を削除
RESTORE_TABLE_STATS特定時刻の統計情報に復元
RESTORE_SCHEMA_STATSスキーマ全体を特定時刻に復元
EXPORT_TABLE_STATS統計情報をstattabにエクスポート
IMPORT_TABLE_STATSstattabから統計情報をインポート
CREATE_STAT_TABLEstattab(中間テーブル)を作成

よくある質問(FAQ)

Q. 統計情報をロックしても手動で更新できますか?

FORCE => TRUE オプションを指定することでロック中でも強制更新できます。

sql

DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'..', TABNAME=>'..', FORCE=>TRUE);

Q. 統計情報を復元できる期間はどれくらいですか?

デフォルトは31日間(設定変更可能)。この期間内であれば任意の時刻の統計情報に戻せます。

Q. 検証環境に本番の統計情報を入れる意味はありますか?

あります。本番と検証でデータ量が違うと、異なる実行計画が使われてしまいます。本番統計情報をインポートすることで、検証環境でも本番に近い実行計画での動作確認が可能になります。


まとめ

  • 夜間の自動統計収集で実行計画が変わる → LOCK_TABLE_STATS で固定化
  • 統計収集後に遅くなった → RESTORE_TABLE_STATS で以前の状態に復元
  • 本番と同じ動作を検証環境で再現したい → EXPORT/IMPORT_TABLE_STATS で移行

統計情報を制御する知識は、Oracleのパフォーマンス維持に欠かせません。基本の収集(GATHER)だけでなく、ロック・削除・復元もマスターして、より安定したOracle運用を実現してください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITの事や自分の経験談など綴っていきたいと思っています。

コメント

コメントする

CAPTCHA


目次