CDB構成におけるオプティマイザ統計の管理と注意点

CDB/PDB(マルチテナント)

Oracle Database 12c以降で導入されたCDB(Container Database)構成では、SQLの実行計画を最適化するためのオプティマイザ統計各コンテナ(CDB$ROOT / PDB)で独立して管理されます。

本記事では、CDB構成における統計情報の基本的な考え方、収集方法、注意点について、図解を交えて詳しく解説します。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?


📚 そもそもオプティマイザ統計とは?

オプティマイザ統計とは、OracleがSQLの実行計画を決定する際に使用する「表や索引のデータ量・カーディナリティなどの情報」です。

例:DBMS_STATSパッケージを使って表やインデックスに統計情報を収集します。


🏗 CDB構成における統計の分離イメージ

+----------------------------+
| CDB$ROOT |
| → Oracle内部辞書用統計 |
+----------------------------+

├─+----------------------------+
│ | PDB1 |
│ | → SCOTTユーザーなどの統計 |
│ +----------------------------+

└─+----------------------------+
| PDB2 |
| → 各ユーザー専用統計 |
+----------------------------+
  • 各コンテナの統計は完全に独立
  • 他のコンテナでの統計収集は一切影響なし

🧪 統計収集の基本操作

✅ PDBでユーザースキーマの統計を収集

ALTER SESSION SET CONTAINER = PDB1;

BEGIN
DBMS_STATS.GATHER_SCHEMA_STATS('SCOTT');
END;
/

☝️ CDB$ROOTで統計を収集しても、PDBの統計は更新されません。 逆に、PDBで統計を収集しても、CDB$ROOTには影響しません。


⚠ 統計収集が「別のコンテナに影響しない」ことの解説

実行場所影響範囲補足
CDB$ROOTCDB辞書表・共通情報各PDBのユーザーデータは含まれない
各PDB(例:PDB1)PDB内のユーザー表他のPDB(例:PDB2)には影響しない

❌ NG例(誤解しやすい)

-- CDB$ROOTで以下を実行しても…
EXEC DBMS_STATS.GATHER_DATABASE_STATS;

PDB1PDB2のユーザースキーマには統計は収集されません

SQL> alter session set container=pdb01;

セッションが変更されました。

SQL> show con_name

CON_NAME
------------------------------
PDB01
SQL> EXECUTE DBMS_STATS.GATHER_DATABASE_STATS; ★PDB01 で統計情報取得

PL/SQLプロシージャが正常に完了しました。

SQL> set lin 1000 pages 1000
SQL> col table_name for a50
SQL> select table_name, num_rows, last_analyzed from dba_tab_statistics;

TABLE_NAME NUM_ROWS LAST_ANA
-------------------------------------------------- ---------- --------
IND$ 2909 25-05-01 ★収集された
CDEF$ 7087 25-05-01 ★
CLU$ 10 25-05-01 ★
UNDO$ 21 25-05-01 ★
CCOL$ 8852 25-05-01 ★

:

SQL> alter session set container=pdb02;

セッションが変更されました。

SQL> show con_name

CON_NAME
------------------------------
PDB02
SQL> set lin 1000 pages 1000
SQL> col table_name for a50
SQL> select table_name, num_rows, last_analyzed from dba_tab_statistics;

TABLE_NAME NUM_ROWS LAST_ANA
-------------------------------------------------- ---------- --------
IND$ 2908 25-04-04 ★収集されていない
CDEF$ 7086 25-04-04
CLU$ 10 19-04-17
UNDO$ 21 25-04-04
CCOL$ 8851 25-04-04

:

SQL> alter session set container=cdb$root;

セッションが変更されました。

SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
SQL> EXECUTE DBMS_STATS.GATHER_DATABASE_STATS; ★CDB$ROOT で統計情報取得

PL/SQLプロシージャが正常に完了しました。

SQL> set lin 1000 pages 1000
SQL> col table_name for a50
SQL> select table_name, num_rows, last_analyzed from dba_tab_statistics;

TABLE_NAME NUM_ROWS LAST_ANA
-------------------------------------------------- ---------- --------
TS$ 6 25-05-01 ★収集された
ICOL$ 5012 25-05-01 ★
USER$ 132 25-05-01 ★
CDEF$ 7251 25-05-01 ★
CCOL$ 8852 25-05-01 ★

:

SQL> alter session set container=pdb02;

セッションが変更されました。

SQL> show con_name

CON_NAME
------------------------------
PDB02
SQL> set lin 1000 pages 1000
SQL> col table_name for a50
SQL> select table_name, num_rows, last_analyzed from dba_tab_statistics;

TABLE_NAME NUM_ROWS LAST_ANA
-------------------------------------------------- ---------- --------
IND$ 2908 25-04-04 ★収集されていない
CDEF$ 7086 25-04-04
CLU$ 10 19-04-17
UNDO$ 21 25-04-04
CCOL$ 8851 25-04-04

:

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?


🔄 自動統計収集(Auto Task)はPDB単位で動作

Oracleには統計情報の自動収集機能があります。これは各PDBごとに動作します。

自動収集の確認方法

-- CDB$ROOTにて
SELECT CLIENT_NAME, STATUS, CON_ID
FROM CDB_AUTOTASK_CLIENT;

CON_IDごとに自動統計収集が有効か確認できます。


📋 統計の確認方法(PDB)

SELECT table_name, num_rows, last_analyzed
FROM dba_tab_statistics
WHERE owner = 'SCOTT';

このビューも現在のコンテナに応じた内容が表示されます。


📌 よくある誤解と正しい運用

誤解正しい知識
CDB$ROOTで統計を収集すればPDBにも反映される各コンテナ(PDB含む)で独立して収集が必要
自動統計収集はCDB単位で動作する各PDBごとにスケジュールされている
DBA_TAB_STATISTICSで全ての統計が確認できる現在のコンテナに限定された統計しか見えない

🔧 PDBごとに統計収集をスケジューリングする例

BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'STATS_JOB_SCOTT',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(''SCOTT''); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;BYHOUR=2',
enabled => TRUE
);
END;
/

✅ まとめ

観点ポイント
統計の分離CDB$ROOTと各PDBの統計は独立して管理される
自動収集PDB単位で自動収集される(設定は個別)
手動収集各PDBに切り替えてからDBMS_STATSを実行する必要がある
誤解を防ぐために各PDBで明示的に統計を収集・確認・スケジューリングすること

🧩 補足:現在のコンテナを確認するコマンド

SHOW CON_NAME;

PDBに切り替えるには:

ALTER SESSION SET CONTAINER = PDB1;

CDB構成では「コンテナ間の完全な分離性」が特徴であり、オプティマイザ統計もその例外ではありません。
正しく統計を管理・収集することで、SQLの実行計画を最適化し、パフォーマンスを維持しましょう。

[参考]
4 CDBの作成および構成

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

コメント

タイトルとURLをコピーしました