Oracle12cから動的統計と呼称するようになったそうです。ハードパースが行われる際、テーブルやインデックスの統計情報が存在しない又は古くなっている場合、自動的に統計情報をサンプリング(*1)し共有プールに格納され利用されます。通常の統計情報はデータディクショナリに格納(SYSTEM表領域に格納)されるので永続しますが、これは共有プールに一時的に保存されるだけのようです。実際動的統計が動作後にDBA_TAB_STATISTICSやDBA_IND_STATISTICSを確認しても取得されている事は確認できません。デフォルトでは64ブロック(一般的には8192 * 64 / 1024 = 512MB)のサンプリングが行われます。
(*1)初期化パラメータ(optimizer_dynamic_sampling)によって定義されています。デフォルトは「ハードパース対象のSQLに含まれるテーブルの1つにでも統計情報が存在しない場合は動的統計の動作対象」となっています。
オプティマイザ統計の管理: 高度なトピック
This chapter explains advanced concepts and tasks relating to optimizer statistics management, including extended statis...
動的統計の確認SQL
select NAME,TYPE,VALUE from v$parameter where NAME = 'optimizer_dynamic_sampling' ;
確認例
SQL> set sqlformat ansiconsole
SQL> select NAME,TYPE,VALUE from v$parameter
2 where NAME = 'optimizer_dynamic_sampling'
3 ;
NAME TYPE VALUE
_____________________________ _______ ________
optimizer_dynamic_sampling 3 2
SQL>
ヒント句を使うと個別でレベル指定できます(取得しなくもできます)
autotraceで確認します。
-- 以下tbl37は統計情報の取得をしていないので動的統計が動作し、autotraceのNoteにその旨出力されます。
SQL> select * from tbl37 where col4 ='西本';
実行計画
----------------------------------------------------------
Plan hash value: 3386457299
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 161 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TBL37 | 1 | 161 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TBL37_IDX04 | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL4"='西本')
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
779 bytes sent via SQL*Net to client
330 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
-- 次に ヒント句でサンプリングを行わないようにします。
-- すると今度はNoteに「dynamic statistics used」のキーワードが出力されません
SQL> select /*+ dynamic_sampling(0) */ * from tbl37 where col4 ='西本';
実行計画
----------------------------------------------------------
Plan hash value: 3386457299
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4625 | 727K| 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TBL37 | 4625 | 727K| 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TBL37_IDX04 | 1850 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL4"='西本')
統計
----------------------------------------------------------
1 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
779 bytes sent via SQL*Net to client
357 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>