OceanBaseデータベースでは、パーティションテーブルの統計情報管理は パーティションレベルの統計情報 と グローバル統計情報 に分かれ、この統計情報メカニズムはパーティションテーブルにのみ適用されます。非パーティションテーブル(つまり通常の単一テーブル)では、パーティション統計や推論ロジックは存在せず、単一のグローバル統計情報のみが存在します。
OceanBaseのパーティションテーブル統計情報メカニズムには以下の特徴があります:
- グローバルとパーティションの統計を区別する:両者は独立して保存され、
partition_idによって区別されます。 - デフォルトで同時に収集する:
APPROX_GLOBAL AND PARTITIONの粒度では、グローバルとパーティションの統計を同時に収集します。 - 欠落または期限切れの統計を自動的に検出する:欠落または期限切れの統計情報を自動的に検出し、収集をトリガーします。
- パーティション統計に基づいてグローバル統計を推論する:パーティション統計の基本統計情報に基づいて、グローバル基本統計情報を推論し、グローバル統計情報のタイムリーさと正確性を向上させます。
本記事では、OceanBaseがパーティションテーブルに対して採用している統計情報収集戦略と自動更新ルールについて詳細に説明します。
デフォルトの集計戦略
OceanBaseは、すべてのパーティションテーブルに対してデフォルトでAPPROX_GLOBAL AND PARTITION粒度で統計情報を収集します(DBMS_STATSパッケージのGATHER_INDEX_STATSプロシージャを使用します)。この戦略では、システムはパーティションレベルの統計情報とグローバル統計情報の2種類の統計情報を同時に生成します。
パーティションレベルの統計情報
各パーティションの独立した統計情報を収集します:
- 基本統計:列の最小値(min)、最大値(max)、異なる値の数(NDV)など;
- ヒストグラム:データの分布特性を表現するために使用されます。
グローバル統計情報
- 基本統計情報(min、max、異なる値の数など):各パーティションの基本統計情報から推論して合成されます(例:グローバルmin = すべてのパーティションのminの最小値);
- グローバルヒストグラム:パーティションの結果から推論することはできず、テーブル全体をサンプリングして収集する必要があります。
グローバル基本統計情報はテーブル全体をスキャンする必要がないため、大規模なパーティションテーブルの統計情報収集効率を大幅に向上させ、特にTB/PB規模のAPシナリオに適しています。
自動更新メカニズム
統計情報のタイムリーさを確保するため、OceanBaseは自動検出と更新のメカニズムを内蔵しています。データ変更率に基づいて、必要に応じて統計情報を更新します。
グローバル統計情報の更新トリガー
以下のいずれかの条件が満たされると、グローバル統計情報の更新がトリガーされます。
- グローバル統計情報の不足:テーブルにグローバル統計情報が存在しない場合。
- グローバルデータの期限切れ:テーブル全体の行数変更率が10%以上(
STALE_PERCENTで制御)。 - 任意のパーティションの統計情報の期限切れ:グローバルデータが変更されていない場合でも、あるパーティションの統計情報が期限切れになると、グローバル統計情報の更新がトリガーされます。これにより、一貫性が保たれます。
更新プロセス:
- グローバル基本統計:パーティションレベルの統計情報から導出されます(最小値、最大値、異なる値の数など)。
- グローバルヒストグラム:ヒストグラムは現在、パーティションの結果に基づいて推導生成することはできないため、個別に収集する必要があります。
パーティションレベルの統計情報の更新トリガー
単一パーティションの統計情報は、以下の条件が満たされた場合に更新されます。
- パーティションの統計情報の不足:あるパーティションに統計情報が存在しない場合。
- パーティションデータの期限切れ:そのパーティションの行数変更率が10%以上(
STALE_PERCENTで制御)。
更新プロセス:
- 期限切れのパーティションの統計情報を再収集します。
- グローバル統計情報を再収集します。
STALE_PERCENTの設定方法
ユーザーはDBMS_STATSパッケージを使用して、期限切れのしきい値を柔軟に調整できます。
-- グローバルデフォルト値を設定する(すべての新規テーブルに影響)
CALL dbms_stats.set_global_prefs('STALE_PERCENT', '50');
-- スキーマレベルで設定する
CALL dbms_stats.set_schema_prefs('MY_SCHEMA', 'STALE_PERCENT', '30');
-- テーブルレベルで設定する
CALL dbms_stats.set_table_prefs('MY_SCHEMA', 'MY_TABLE', 'STALE_PERCENT', '20');
自動検出機能
OceanBaseシステムのバックグラウンドで、以下の検出タスクが継続的に実行されます。
- 統計情報ステータスの確認:既存のすべてのグローバルおよびパーティション統計情報をスキャンします。
- 期限切れパーティションの検出:各パーティションが期限切れまたは不足しているかどうかを確認します。
- 不足統計の検出:不足している項目を自動的にマークし、収集キューに追加します。
- 独立したトリガーによる更新:グローバルおよびパーティション統計情報の独立したトリガーによる更新をサポートし、互いに影響しません。
主要パラメータ
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
STALE_PERCENT |
10(10%) | ストアドプロシージャ(set_schema_prefs、set_table_prefs)のパラメータで、統計情報の有効期限の変更しきい値を判断します |
| デフォルトの収集粒度 | APPROX_GLOBAL AND PARTITION |
パーティションテーブルにのみ適用されます。非パーティションテーブルでは GLOBAL を使用します(DBMS_STATS パッケージの GATHER_INDEX_STATS プロシージャを使用します) |
パーティションテーブルと非パーティションテーブルの比較
| 特性 | 分区表 | 非分区表(単一テーブル) |
|---|---|---|
| 統計タイプ | グローバル + パーティション | みなし |
| グローバルベース統計のソース | パーティション統計から導出 | 全テーブルスキャンで生成 |
| パーティションプルーニングの最適化をサポートするか | はい | いいえ |
| デフォルトの収集粒度 | APPROX_GLOBAL AND PARTITION |
GLOBAL |
例:OceanBaseのパーティションテーブル統計情報管理
この例では、OceanBaseデータベース(MySQLモード)を使用して、パーティションテーブルを作成し、その統計情報の収集と自動更新の動作を確認し、グローバル統計情報がパーティション統計情報から導出される様子を示します。
ステップ1:テスト用パーティションテーブルを作成する
-- データベースとユーザーの作成(存在しない場合にのみ)
CREATE DATABASE IF NOT EXISTS sales_db;
USE sales_db;
-- RANGEパーティションによる販売記録テーブルの作成
CREATE TABLE sales (
id BIGINT NOT NULL,
region VARCHAR(50),
amount DECIMAL(10,2),
sale_date DATE,
PRIMARY KEY (id, sale_date)
) PARTITION BY RANGE COLUMNS(sale_date) (
PARTITION p2023_q1 VALUES LESS THAN ('2023-04-01'),
PARTITION p2023_q2 VALUES LESS THAN ('2023-07-01'),
PARTITION p2023_q3 VALUES LESS THAN ('2023-10-01'),
PARTITION p2023_q4 VALUES LESS THAN ('2024-01-01')
);
ステップ2:初期データを挿入する
-- 各パーティションにテストデータを挿入
INSERT INTO sales VALUES
(1, 'North', 1500.00, '2023-01-15'),
(2, 'South', 2300.50, '2023-02-20'),
(3, 'East', 980.75, '2023-04-10'),
(4, 'West', 3200.00, '2023-06-25'),
(5, 'North', 1800.25, '2023-07-05'),
(6, 'South', 2100.00, '2023-09-18');
ステップ3:統計情報を収集する(デフォルト粒度:APPROX_GLOBAL AND PARTITION)
CALL DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'sales_db',
tabname => 'sales',
method_opt => 'FOR ALL COLUMNS SIZE AUTO',
granularity => 'APPROX_GLOBAL AND PARTITION'
);
ステップ4:統計情報を確認する
グローバルテーブルレベルの統計情報を確認する
SELECT
TABLE_NAME,
OBJECT_TYPE,
NUM_ROWS,
AVG_ROW_LEN,
LAST_ANALYZED
FROM oceanbase.DBA_TAB_STATISTICS
WHERE OWNER = 'SALES_DB' AND TABLE_NAME = 'SALES'
ORDER BY OBJECT_TYPE;
期待される結果:
+------------+-------------+----------+-------------+----------------------------+
| TABLE_NAME | OBJECT_TYPE | NUM_ROWS | AVG_ROW_LEN | LAST_ANALYZED |
+------------+-------------+----------+-------------+----------------------------+
| sales | PARTITION | 2 | 73 | 2026-01-14 10:45:58.067339 |
| sales | PARTITION | 2 | 72 | 2026-01-14 10:45:58.067339 |
| sales | PARTITION | 2 | 73 | 2026-01-14 10:45:58.067339 |
| sales | PARTITION | 0 | 0 | 2026-01-14 10:45:58.067339 |
| sales | TABLE | 6 | 72 | 2026-01-14 10:45:58.079250 |
+------------+-------------+----------+-------------+----------------------------+
5 rows in set
グローバル列レベルの統計情報を確認する(amount列など)
SELECT
COLUMN_NAME,
NUM_DISTINCT,
LOW_VALUE,
HIGH_VALUE,
NUM_NULLS,
HISTOGRAM
FROM oceanbase.DBA_TAB_COL_STATISTICS
WHERE OWNER = 'SALES_DB'
AND TABLE_NAME = 'SALES'
AND COLUMN_NAME = 'AMOUNT';
期待される結果:
+-------------+--------------+-----------+------------+-----------+-----------+
| COLUMN_NAME | NUM_DISTINCT | LOW_VALUE | HIGH_VALUE | NUM_NULLS | HISTOGRAM |
+-------------+--------------+-----------+------------+-----------+-----------+
| amount | 6 | 980.75 | 3200.00 | 0 | NULL |
+-------------+--------------+-----------+------------+-----------+-----------+
1 row in set
パーティションレベルの列統計情報を確認する(p2023_q1パーティションのamount列など)
SELECT
PARTITION_NAME,
COLUMN_NAME,
NUM_DISTINCT,
LOW_VALUE,
HIGH_VALUE,
NUM_NULLS
FROM oceanbase.DBA_PART_COL_STATISTICS
WHERE OWNER = 'SALES_DB'
AND TABLE_NAME = 'SALES'
AND PARTITION_NAME = 'P2023_Q1'
AND COLUMN_NAME = 'AMOUNT';
期待される結果:
+----------------+-------------+--------------+-----------+------------+-----------+
| PARTITION_NAME | COLUMN_NAME | NUM_DISTINCT | LOW_VALUE | HIGH_VALUE | NUM_NULLS |
+----------------+-------------+--------------+-----------+------------+-----------+
| p2023_q1 | amount | 2 | 1500.00 | 2300.50 | 0 |
+----------------+-------------+--------------+-----------+------------+-----------+
1 row in set
ステップ5:自動更新メカニズムを検証する(オプション)
-- p2023_q4に新しいデータを挿入する(変更率が10%を超えるようにシミュレート)
INSERT INTO sales
SELECT 1000 + n, 'Central', ROUND(RAND()*5000, 2), '2023-11-01'
FROM (SELECT @n := @n + 1 AS n FROM information_schema.columns a, information_schema.columns b, (SELECT @n := 0) r LIMIT 50) t;
-- 後続の自動検出を待機するか、手動でトリガーする
CALL DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO();
-- ここでは、変更率がSTALE_PERCENT(デフォルト値は10%)に達した場合、システムが自動的にstaleとマークし、統計情報の収集をトリガーする可能性があります
-- LAST_ANALYZEDの時間値が更新されているか再度確認する
SELECT PARTITION_NAME, LAST_ANALYZED
FROM oceanbase.DBA_TAB_STATISTICS
WHERE OWNER = 'SALES_DB' AND TABLE_NAME = 'SALES'
ORDER BY PARTITION_NAME;
期待される結果:
+----------------+----------------------------+
| PARTITION_NAME | LAST_ANALYZED |
+----------------+----------------------------+
| NULL | 2026-01-14 10:45:58.079250 |
| p2023_q1 | 2026-01-14 10:45:58.067339 |
| p2023_q2 | 2026-01-14 10:45:58.067339 |
| p2023_q3 | 2026-01-14 10:45:58.067339 |
| p2023_q4 | 2026-01-14 10:45:58.067339 |
+----------------+----------------------------+
5 rows in set
関連ドキュメント
関連する PL プロシージャの参考ドキュメントは次のとおりです: