OceanBaseデータベースのオプティマイザーは、主に DBMS_STATS パッケージと ANALYZE ステートメントの2つの方法で統計情報を手動で収集します。
説明
OceanBaseデータベースは現在、統計情報収集時間の見積もりをサポートしていません。そのため、統計情報の収集を完了するために、ob_query_timeout を十分に長く設定することを推奨します。特にスキーマレベルの統計情報を収集する際、タイムアウトにより中断された場合でも、既に収集済みの統計情報は保持されます。
使用方法と制限
- セッションレベルで ob_query_timeout 変数を大きく設定することを推奨します。この方法は現在のセッションのみに影響し、他の操作には干渉しません。
手順
ステージ |
操作 |
コマンド/ビュー |
|---|---|---|
| 準備 | ob_query_timeoutを増やす |
SET SESSION ob_query_timeout = 36000000000; |
| 実行 | DBMS_STATSまたはANALYZEを呼び出す |
CALL dbms_stats.gather_table_stats(...); |
| 監視 | 収集の進捗と状態を確認する | (G)V$OB_OPT_STAT_GATHER_MONITOR |
| 検証 | 統計情報が書き込まれているか、期限切れかを確認する | DBA_TAB_STATISTICS、DBA_TAB_COL_STATISTICS(およびヒストグラム関連ビュー) |
| 診断 | 失敗や異常を処理する | DBA_OB_TASK_OPT_STAT_GATHER_HISTORY、DBA_OB_TABLE_OPT_STAT_GATHER_HISTORY + 実行計画キャッシュ(Plan Cache)(リフレッシュ/エージングアウトの説明を含む) |
DBMS_STATSパッケージによる統計情報の収集
OceanBaseデータベースのオプティマイザーは、DBMS_STATS (MySQLモード)/DBMS_STATS (Oracleモード) パッケージを利用して、テーブルレベル、スキーマレベルの統計情報およびインデックス統計情報を収集することをサポートしています。これらはそれぞれ、ストアドプロシージャ gather_table_stats、gather_schema_stats、gather_index_stats を呼び出すことで実行されます。
PROCEDURE gather_table_stats (
ownname VARCHAR2,
tabname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE
);
PROCEDURE gather_schema_stats (
ownname VARCHAR2,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE
);
PROCEDURE gather_index_stats (
ownname VARCHAR2,
indname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
stattab VARCHAR2 DEFAULT NULL,
statid VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
no_invalidate BOOLEAN DEFAULT FALSE,
force BOOLEAN DEFAULT FALSE,
tabname VARCHAR2 DEFAULT NULL
);
DBMS_STATS.GATHER_TABLE_STATS (
ownname VARCHAR2,
tabname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT to_degree_type(get_param('DEGREE')),
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE,
hist_est_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
hist_block_sample BOOLEAN DEFAULT NULL
);
DBMS_STATS.GATHER_SCHEMA_STATS (
ownname VARCHAR2,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
block_sample BOOLEAN DEFAULT FALSE,
method_opt VARCHAR2 DEFAULT DEFAULT_METHOD_OPT,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
cascade BOOLEAN DEFAULT NULL,
no_invalidate BOOLEAN DEFAULT FALSE,
stattype VARCHAR2 DEFAULT 'DATA',
force BOOLEAN DEFAULT FALSE);
DBMS_STATS.GATHER_INDEX_STATS (
ownname VARCHAR2,
indname VARCHAR2,
partname VARCHAR2 DEFAULT NULL,
estimate_percent NUMBER DEFAULT AUTO_SAMPLE_SIZE,
stattab VARCHAR2 DEFAULT NULL,
statown VARCHAR2 DEFAULT NULL,
degree NUMBER DEFAULT NULL,
granularity VARCHAR2 DEFAULT DEFAULT_GRANULARITY,
no_invalidate BOOLEAN DEFAULT FALSE,
force BOOLEAN DEFAULT FALSE,
tabname VARCHAR2 DEFAULT NULL);
詳細なパラメータの説明については、以下を参照してください:
- GATHER_TABLE_STATS (MySQLモード)/GATHER_TABLE_STATS (Oracleモード)
- GATHER_SCHEMA_STATS (MySQLモード)/GATHER_SCHEMA_STATS (Oracleモード)
- GATHER_INDEX_STATS (MySQLモード)/GATHER_INDEX_STATS (Oracleモード)
DBMS_STATS パッケージが提供する収集戦略は、デフォルト設定の Prefs を採用します。Refs の設定に関する詳細は、収集戦略パラメータ(Prefs)管理機能を参照してください。
PROCEDURE GATHER_DATABASE_STATS_JOB_PROC();
例
DBMS_STATSパッケージによる統計情報収集の例は以下のとおりです:
ユーザー
userのテーブルtbl1のグローバルレベルの統計情報を収集します。CALL dbms_stats.gather_table_stats('user', 'tbl1', granularity=>'GLOBAL', method_opt=>'FOR ALL COLUMNS SIZE AUTO');ユーザー
userのテーブルt_part1のパーティションレベルの統計情報を収集します。並列度は64で、データ分布が不均一な列のヒストグラムのみを収集します。CALL dbms_stats.gather_table_stats('user', 't_part1', degree=>'64', granularity=>'PARTITION', method_opt=>'FOR ALL COLUMNS SIZE SKEWONLY');ユーザー
userのテーブルt_subpart1のすべての統計情報を収集します。並列度は128で、データの50%のみを収集し、すべての列のヒストグラムはオプティマイザー内部で決定されます。CALL dbms_stats.gather_table_stats('user', 't_subpart1', degree=>'128', estimate_percent=> '50', granularity=>'ALL', method_opt=>'FOR ALL COLUMNS SIZE AUTO');
gather_table_statsを実行した後、すぐに(G)V$OB_OPT_STAT_GATHER_MONITORをクエリすることで、タスクが開始されたかどうかを確認できます。
テーブルレベルとインデックスレベルの統計情報収集戦略GRANULARITYの関連性
デフォルトでは、テーブルの統計情報を収集する際に、そのテーブルにあるすべてのインデックスの統計情報も収集されます。これは、インデックスの一部の統計情報(行数や平均行長など)がベーステーブルの統計情報から得られるためであり、統計情報の取得を高速化するとともに、テーブル全体のデータを再スキャンすることを回避できます。ローカルインデックスとグローバルインデックスではGRANULARITYに違いがあり、以下の表のとおりです。
指定パーティション |
GRANULARITY |
グローバルインデックス |
ローカルインデックス |
|---|---|---|---|
| いいえ | ALL | GLOBALレベル | ALL |
| いいえ | AUTO | GLOBALレベル | AUTO |
| いいえ | DEFAULT | GLOBALレベル | DEFAULT |
| いいえ | GLOBAL AND PARTITION | GLOBALレベル | GLOBAL AND PARTITION |
| いいえ | APPROX_GLOBAL AND PARTITION | GLOBALレベル | APPROX_GLOBAL AND PARTITION |
| いいえ | GLOBAL | GLOBALレベル | GLOBAL |
| いいえ | PARTITION | GLOBALレベル | PARTITION |
| いいえ | SUBPARTITION | 収集なし | SUBPARTITION |
| はい | ALL | GLOBALレベル | ALL |
| はい | AUTO | GLOBALレベル | AUTO |
| はい | DEFAULT | GLOBALレベル | DEFAULT |
| はい | GLOBAL AND PARTITION | GLOBALレベル | GLOBAL AND PARTITION |
| はい | APPROX_GLOBAL AND PARTITION | 収集なし | APPROX_GLOBAL AND PARTITION |
| はい | GLOBAL | GLOBALレベル | GLOBAL |
| はい | PARTITION | 収集なし | PARTITION |
| はい | SUBPARTITION | 収集なし | SUBPARTITION |
ANALYZEステートメントによる統計情報の収集
OracleモードおよびMySQLモードでは、OceanBaseデータベースはANALYZEステートメントを使用した統計情報の収集をサポートしています。
MySQLモードの ANALYZE 構文は以下のとおりです:
analyze_stmt:
ANALYZE TABLE table_name UPDATE HISTOGRAM ON column_name_list WITH INTNUM BUCKETS
テナントレベルの構成パラメータ enable_sql_extension が TRUE の場合、Oracleモードの構文、つまりOceanBaseデータベースがMySQLモードで提供する拡張構文を使用できます。
analyze_stmt:
ANALYZE TABLE table_name [use_partition] analyze_statistics_clause
MySQLモードにおける ANALYZE ステートメントの統計情報収集例は以下のとおりです:
テーブル
tbl1の統計情報を収集します。列のバケット数は30個です。ANALYZE TABLE tbl1 UPDATE HISTOGRAM ON a, b, c, d WITH 30 BUCKETS;MySQLモードでOracleモードの構文を使用して、ユーザー
testのテーブルtbl1の統計情報を収集します。ALTER SYSTEM SET ENABLE_SQL_EXTENSION = TRUE; ANALYZE TABLE tbl1 COMPUTE STATISTICS FOR ALL COLUMNS SIZE AUTO;
OracleモードにおけるANALYZE構文は以下のとおりです:
analyze_stmt:
ANALYZE TABLE table_name [use_partition] analyze_statistics_clause
use_partition:
PARTITION (parition_name [,partition_name...])
| SUBPARTITION(subpartition_name [,subpartition_name...])
analyze_statistics_clause:
COMPUTE STATISTICS [analyze_for_clause]
| ESTIMATE STATISTICS [analyze_for_clause] [SAMPLE INTNUM {ROWS | PERCENTAGE}]
analyze_for_clause:
FOR TABLE
| FOR ALL [INDEXED | HIDDEN] COLUMNS [size_clause]
| FOR COLUMNS [size_clause] column [size_clause] [,column [size_clause]...]
size_clause:
SIZE integer
| SIZE REPEAT
| SIZE AUTO
| SIZE SKEWONLY
column:
column_name
| (column_name [,column_name])
上記構文において、指定された列の統計情報ヒストグラム収集方法はDBMS_STATSパッケージのmethod_opt構文と同じです。詳細については、method_optを参照してください。
DBMS_STATSパッケージによる統計情報収集方法と比較して、ANALYZEステートメントはそれほど豊富な戦略設定を提供していません。ANALYZEステートメントがGLOBALレベルの統計情報のみを収集することをサポートするための規則として、use_partition構文でpartition_nameにテーブル名を設定するだけでよいというものがあります。
OracleモードにおけるANALYZEステートメントの統計情報収集例は以下のとおりです:
ユーザー
userのテーブルtbl1の統計情報を収集します。ANALYZE TABLE tbl1 COMPUTE STATISTICS FOR ALL COLUMNS SIZE AUTO;ユーザー
userのテーブルt_part1のGLOBALレベルの統計情報を収集し、データ分布が不均一な列のヒストグラムのみを収集します。ANALYZE TABLE t_part1 PARTITION (t_part1) COMPUTE STATISTICS FOR ALL COLUMNS SIZE SKEWONLY;ユーザー
userのテーブルt_subpart1のパーティションp0sp0とp1sp2の統計情報を収集します。すべての列のヒストグラムはオプティマイザー内部で決定されます。ANALYZE TABLE t_subpart1 SUBPARTITION(p0sp0,p1sp2) COMPUTE STATISTICS FOR ALL COLUMNS SIZE AUTO;
手動統計情報収集の適用シナリオ
非パーティションテーブルの統計情報収集
テーブルのデータ量と列数の積が1億を超えない場合、以下のコマンドを使用して非パーティションテーブルの統計情報を収集することを推奨します。以下の例では、テーブル test.t1 は10列あり、データ量は100万行です。
CREATE TABLE test.t1(c1 INT, c2 INT, c3 INT, c4 INT, c5 INT, c6 INT, c7 INT, c8 INT, c9 INT, c10 INT);
CREATE TABLE t2 (c1 INT PRIMARY KEY);
INSERT INTO t2 VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
INSERT /*+APPEND*/ INTO t1 SELECT * FROM (SELECT s0.c1 c1, s1.c1 c2, s2.c1 c3, s3.c1 c4, s4.c1 c5, s5.c1 c6, s0.c1 * 10 c7, s1.c1 * 10 c8, s2.c1 * 10 c9, s3.c1 * 10 c10 FROM t2 s0, t2 s1, t2 s2, t2 s3, t2 s4, t2 s5);
# ヒストグラムを収集しないシナリオ
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1', method_opt=>'for all columns size 1');
# ヒストグラムを収集するシナリオでデフォルトポリシーを使用する
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1');
テーブルのデータ量と列数の積が1億を超える場合、データの業務状況とシステムリソースに応じて適切な並列度を設定し、統計情報の収集を高速化することを推奨します。以下の例では、テーブル test.t1 のデータ量が1000万行に増加したため、並列度8を使用します。
# ヒストグラムを収集しないシナリオ
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1', degree=>8, method_opt=>'for all columns size 1');
# ヒストグラムを収集するシナリオでデフォルトポリシーを使用する
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't1', degree=>8);
パーティションテーブルの統計情報収集
非パーティションテーブルと比較して、パーティションテーブルの統計情報収集戦略では、パーティションの統計情報収集を考慮する必要があります。システムリソースに余裕がある場合、パーティションテーブルの統計情報収集戦略としては、非パーティションテーブルの並列度をさらに2倍に増やすことを推奨します。
以下の例では、同じシナリオで test.t_part テーブルは10列あり、データ量も100万行です。パーティションの統計情報収集が追加されたため、並列度は2に増加しています。
CREATE TABLE t_part(c1 INT, c2 INT, c3 INT, c4 INT, c5 INT, c6 INT, c7 INT, c8 INT, c9 INT, c10 INT) PARTITION BY HASH(c1) PARTITIONS 128;
CREATE TABLE t2 (c1 INT PRIMARY KEY);
INSERT INTO t2 VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
INSERT /*+APPEND*/ INTO t_part SELECT * FROM (SELECT s0.c1 c1, s1.c1 c2, s2.c1 c3, s3.c1 c4, s4.c1 c5, s5.c1 c6, s0.c1 * 10 c7, s1.c1 * 10 c8, s2.c1 * 10 c9, s3.c1 * 10 c10 FROM t2 s0, t2 s1, t2 s2, t2 s3, t2 s4, t2 s5);
パーティションテーブルについては、上記の並列度の増加に加えて、パーティション推定方式による収集も検討できます。これは、パーティションの統計情報を収集し、それに基づいてグローバルな統計情報を推定することで、収集効率を向上させる方法です。例えば、同じシナリオで並列度を増やさず、収集するパーティションの方式を調整する例を以下に示します。
# ヒストグラムを収集しないシナリオ
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't_part', granularity=>'APPROX_GLOBAL AND PARTITION', method_opt=>'for all columns size 1');
# ヒストグラムを収集するシナリオでデフォルトの戦略を使用
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 't_part', granularity=>'APPROX_GLOBAL AND PARTITION');
パーティションテーブルの統計情報の収集と更新戦略、および詳細な例については、パーティションテーブルの統計情報の収集と更新戦略を参照してください。
スキーマ(データベース)レベルの統計情報収集
単一テーブルの統計情報を手動で収集するほかに、OceanBaseデータベースのDBMS_STATSシステムパッケージは、ユーザー配下のすべてのテーブルに対する統計情報収集も提供します。
説明
この機能は、OceanBaseデータベースV4.xバージョンのデュアルモードおよびOceanBaseデータベースV3.2.xバージョンのOracleモードでのみサポートされています。
特定のユーザー配下のすべてのテーブルの統計情報を収集するのは時間がかかるため、業務のオフピーク時にこの機能を使用することを推奨します。
そのユーザー配下のすべてのテーブルのデータ量が小さなテーブル(データ量が100万行を超えない場合)のみであれば、以下の例に示すように、test ユーザーの統計情報を収集するコマンドを直接使用できます。
# ヒストグラムを収集しない場合
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test', method_opt=>'for all columns size 1');
# ヒストグラムを収集する場合でデフォルトポリシーを使用する場合
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test');
収集するユーザー配下に大規模なテーブル(行数が数千万レベル)が存在する場合、業務のオフピーク時に並列度を上げて収集できます:
# ヒストグラムを収集しない場合
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test', degree=>'16', method_opt=>'for all columns size 1');
# ヒストグラムを収集する場合でデフォルトポリシーを使用する場合
CALL DBMS_STATS.GATHER_SCHEMA_STATS('test', degree=>'16');
ユーザー配下に超大規模なテーブル(行数が1億を超える)が存在する場合、超大規模なテーブルに対して並列度を上げて個別に収集し、その後超大規模なテーブルの統計情報をロックした上で上記のコマンドを使用してユーザー全体を収集し、収集完了後に超大規模なテーブルの統計情報をアンロックし、その後は増分モードで収集する方法を選択できます。例:
CALL DBMS_STATS.GATHER_TABLE_STATS('test', 'big_table', degree=>128, method_opt=>'for all columns size 1');
CALL DBMS_STATS.LOCK_TABLE_STATS('test','big_table');
CALL DBMS_STATS.GATHER_SCHEMA_STATS('TEST', degree=>'16', method_opt=>'for all columns size 1');
CALL DBMS_STATS.UNLOCK_TABLE_STATS('test','big_table');
毎回の収集後には、必ずヘルスチェックを実行してください:
-- 例:test.t1が正常に収集されたかどうかを確認する
SELECT table_name, num_rows, last_analyzed
FROM oceanbase.DBA_TAB_STATISTICS
WHERE owner = 'test' AND table_name = 'T1' AND object_type = 'TABLE';
統計情報収集の進捗とヘルス状態の監視
なぜ監視が必要か?統計情報の収集には数分から数時間かかる場合があります。必要なことは以下の通りです:
- タスクがまだ実行中かどうかをリアルタイムで把握する
- タスクが停止または失敗していないかどうかを判断する
- 収集結果が有効かどうかを検証する
- 統計情報が「古くなっている」または「歪んでいる」かどうかを評価する
統計情報収集の進捗状況を照会する
OceanBaseデータベースはV4.2.0バージョンから統計情報収集モニタリング診断機能をサポートしています。手動または自動で統計情報収集を開始した後、(G)V$OB_OPT_STAT_GATHER_MONITORビューを使用してリアルタイムの収集状態と進捗を確認できます。
このビューのフィールドの意味、例、その他の診断方法については、統計情報収集モニタリング診断を参照してください。
現在実行中の収集タスクを確認する
説明
- MySQLモードでは通常
oceanbase.GV$OB_OPT_STAT_GATHER_MONITOR(またはoceanbase.V$OB_OPT_STAT_GATHER_MONITOR)を使用します。 - Oracleモードでは通常
SYS.GV$OB_OPT_STAT_GATHER_MONITOR(またはSYS.V$OB_OPT_STAT_GATHER_MONITOR)を使用します。
SELECT
tenant_id,
svr_ip,
svr_port,
session_id,
trace_id,
task_id,
type,
task_start_time,
task_duration_time,
task_table_count,
completed_table_count,
running_table_owner,
running_table_name,
running_table_duration_time,
running_table_progress
FROM oceanbase.GV$OB_OPT_STAT_GATHER_MONITOR
WHERE type = 'MANUAL GATHER';
フィールド |
説明 |
|---|---|
TASK_TABLE_COUNT |
このタスクで収集が必要なテーブルの数 |
COMPLETED_TABLE_COUNT |
このタスクで完了したテーブルの数 |
RUNNING_TABLE_OWNER / RUNNING_TABLE_NAME |
現在収集中のテーブル |
RUNNING_TABLE_PROGRESS |
現在収集中のテーブルの進捗状況(文字列形式で表示) |
「現在のテナントが現在のOBServerノード上で」のリアルタイム状態を確認したい場合は、V$OB_OPT_STAT_GATHER_MONITORを使用してください。
過去のタスク履歴を確認する(タスクレベル)
-- 手動収集タスクの実行履歴を照会する
SELECT
tenant_id,
task_id,
type,
status,
table_count,
failed_count,
start_time,
end_time
FROM oceanbase.DBA_OB_TASK_OPT_STAT_GATHER_HISTORY
WHERE type = 'MANUAL GATHER'
ORDER BY start_time DESC;
過去のタスク履歴を確認する(テーブルレベル)
-- 手動収集プロセスで失敗したテーブルを照会する(失敗がなければ返されない)
SELECT
owner,
table_name,
task_id,
status,
start_time,
end_time,
stat_refresh_failed_list,
properties
FROM oceanbase.DBA_OB_TABLE_OPT_STAT_GATHER_HISTORY
WHERE status = 'FAILED'
ORDER BY start_time DESC;
STAT_REFRESH_FAILED_LISTは「統計情報の収集は完了したが、統計情報キャッシュのリフレッシュに失敗した」ノードのリストを表します。このフィールドが表示された場合は、ビュー情報と組み合わせて関連ノードの状態を調査し、必要に応じてPlan Cacheをリフレッシュすることを推奨します。
統計情報の有効性または健全性の検証
収集が完了した後、統計情報が書き込まれ、利用可能な状態にあることを確認する必要があります。
テーブルレベル統計情報の存在確認
説明
- MySQLモードでは、
oceanbase.DBA_TAB_STATISTICS、oceanbase.DBA_TAB_COL_STATISTICSなどのビューを使用できます。 - Oracleモードでは、
SYS.DBA_TAB_STATISTICS、SYS.DBA_TAB_COL_STATISTICSなどのビューを使用できます。
SELECT
table_name,
num_rows, -- 行数
avg_row_len, -- 平均行長
sample_size, -- サンプルサイズ
last_analyzed, -- 最後の収集時間
stale_stats, -- 有効期限切れかどうか
stattype_locked -- ロックされているかどうか
FROM oceanbase.DBA_TAB_STATISTICS
WHERE owner = 'test' AND table_name = 'T1' AND object_type = 'TABLE';
健全性の指標:
last_analyzedが最近の日時(今回の収集日時と一致)であること。num_rows/sample_sizeなどの重要なフィールドがNULLではなく、業務規模とおおむね一致していること。stale_stats = 'NO'(統計情報が有効期限切れではないこと)。
列ヒストグラムの生成確認(SIZE > 1を指定した場合)
SELECT
column_name,
num_distinct, -- 異なる値の数
num_nulls, -- NULL値の数
num_buckets, -- バケットの数
histogram, -- ヒストグラムタイプ
last_analyzed
FROM oceanbase.DBA_TAB_COL_STATISTICS
WHERE owner = 'test' AND table_name = 'T1';
ヒストグラムの健全性判断:
histogramフィールドにヒストグラムタイプ(例:HYBRID)が表示され、かつnum_buckets > 1の場合、通常はヒストグラムが生成されています。num_distinct/num_nullsなどの統計値は、業務上の期待値と照合して整合性を確認することを推奨します(サンプリングが小さすぎたり、戦略が不適切だったりして歪みが生じるのを防ぐため)。
統計情報がロックされていないかどうかの確認(自動更新による上書きを防ぐため)
SELECT stattype_locked
FROM oceanbase.DBA_TAB_STATISTICS
WHERE owner = 'test' AND table_name = 'BIG_TABLE' AND object_type = 'TABLE';
stattype_locked = 'ALL':ロックされているNULL:ロックされていない
よくある質問の診断
現象 |
考えられる原因 |
解決策 |
|---|---|---|
| グラフ収集タスクが長時間進まない | テーブルが巨大、並列度が低い、リソース競合 | degreeを増やし、業務の閑散期に実行する |
num_rows = 0またはNULL |
グラフ収集が完了していないか失敗した | DBA_OB_TASK_OPT_STAT_GATHER_HISTORY、DBA_OB_TABLE_OPT_STAT_GATHER_HISTORYを確認する |
| ヒストグラムが生成されていない | method_optでSIZE > 1が指定されていない |
FOR COLUMNS col SIZE 254を明示的に設定する |
| クエリが依然として誤った実行計画で実行される | 統計情報がPlan Cacheを更新していない | ALTER SYSTEM FLUSH PLAN CACHE;を実行する |