テーブル内のデータが大幅に変更されると、統計が古くなる可能性があります。適切な実行計画を作成するには、最新の統計が重要です。
統計が古くなったかどうかをOracleが判断する方法
#(INSERTS + UPDATES + DELETES)> =dba_tablesからのNUM_ROWSの10%の場合、統計は失効していると見なされます:
テーブルの変更を追跡するために必要なパラメータ設定
Oracle 10gより前は、古くなったオブジェクトの統計の自動収集は、テーブルのMONITORINGフラグの設定によって制御されていました。
MONITORINGフラグに応じて、GATHER_STATS_JOBジョブは「GATHEREMPTY」と「GATHERSTALE」を収集しました。フラグが立てられたオブジェクト。
10gでは、MONITORINGおよびNOMONITORINGキーワードは廃止され、無視されます。テーブル監視機能は、STATISTICS_LEVELパラメータによって制御されるようになりました。
STATISTICS_LEVELがBASICに設定されている場合、テーブルの監視は無効になります。
STATISTICS_LEVELがTYPICALに設定されている場合、監視が有効になります。
デフォルトでは、STATISTICS_LEVELがTYPICALに設定され、テーブルの監視が有効になっています。 10g以上でSTATISTICS_LEVELをTYPICALに設定することを強くお勧めします。
これらのパラメータを設定することにより、Oracleは、統計が最後に収集されてからのoracleテーブルのINSERT、UPDATE、およびDELETE操作のおおよその数を追跡します。 「行われた変更」に関するこの情報はSGAで維持され、定期的に(約15分ごとに)SMONがデータをデータディクショナリテーブルにフラッシュします。 dbms_stats.FLUSH_DATABASE_MONITORING_INFO()を呼び出すことにより、情報を手動でフラッシュできます。データディクショナリ情報は、DBA_TAB_MODIFICATIONS、ALL_TAB_MODIFICATIONS、およびUSER_TAB_MODIFICATIONSのビューを通じて表示されます。
Oracleはこれらのビューを使用して、古い統計を持つテーブルを識別します。
テーブル内のデータに10%の変更がある場合は常に、Oracleはその統計が古いと見なします。
古い統計を確認する方法
以下のPLSQLプロシージャは、古い統計であるSCOTTスキーマのすべてのテーブルを検索します
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(ownname=>'SCOTT', objlist=>ObjList, options=>'LIST STALE'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
以下のSQLは、挿入、更新、削除を見つけるためにも使用できます
select u.TIMESTAMP, t.last_analyzed, u.table_name, u.inserts, u.updates, u.deletes, d.num_rows, decode(d.num_rows,0,'Table Stats indicate No Rows', nvl(TO_CHAR(((U.inserts+u.deletes+u.updates)/d.num_rows) * 100,'999.99') ,'Null Value in USER_TAB_MODIFICATIONS') ) percent from user_tables t,USER_TAB_MODIFICATIONS u,dba_tables d where u.table_name = t.table_name and d.table_name = t.table_name and d.owner = '&Owner' and (u.inserts > 3000 or u.updates > 3000 or u.deletes > 3000) order by t.last_analyzed /
これをデータベース全体で実行する場合
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_DATABASE_STATS(objlist=>ObjList, options=>'LIST STALE'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
統計が空のテーブルを表示したい場合は、以下を使用できます
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_DATABASE_STATS(objlist=>ObjList, options=>'LIST EMPTY'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
これで、テーブルリストが見つかったら、これらのテーブルの統計を生成できます。
exec dbms_stats.gather_table_stats('OWNER', 'TABLE_NAME');
以下のコマンドを実行して、スキーマ内のすべての古いオブジェクトの統計を生成することもできます
exec dbms_stats.gather_schema_stats(ownname => '<schema name>', cascade => TRUE, options => 'GATHER AUTO');
Oracle11g以降、STALE_PERCENT統計設定を使用して失効しきい値を設定できます。これは、DBMS_STATS.SET_GLOBAL_PREFSを使用してグローバルに設定することも、DBMS_STATS.SET_TABLE_PREFSを使用してテーブルレベルで設定することもできます。
関連記事
ora-38029:オブジェクト統計はロックされています
11gのスキーマ統計の収集(FND_HISTOGRAM_COLS)
リリース11iおよびR12での統計の収集
11gでの増分統計の収集
方法Oracleでのテーブル監視とSTATISTICS_LEVELとの関係の設定