本記事では、MySQLモードにおける ステップバイステップSQL演習(orders 入門、tbl* 小片段、外部テーブル 全量MVなど)を提供しており、セクションの順序に従って操作できます。マテリアライズドビューによるクエリの高速化 の sales / items メインストーリーの例と組み合わせて使用してください:業務テーブルを通じた完全な演習が必要な場合は、まずこのドキュメントを読んでください。
説明
構文、制限条件などの詳細情報については、次のURLを参照してください:マテリアライズドビューの作成、マテリアライズドビューの更新、マテリアライズドビューによるクエリのリライト。
マテリアライズドビューによるリアルタイムデータウェアハウスの構築:シナリオ選定
リアルタイムデータウェアハウス構築における迅速な意思決定を容易にするため、「データの鮮度要件 → 計算複雑さ → データソースタイプ」の順序で選定します。
ターゲットシナリオ |
推奨機能の組み合わせ |
典型的特徴 |
対応章 |
|---|---|---|---|
| 週次集計ダッシュボード、分単位更新 | REFRESH FAST + 定時スケジューリング |
増分メンテナンスコストが低く、安定した集計口径に適しています | 入門実践;シナリオ2:リアルタイム指標加工パイプライン |
| 詳細ワイドテーブルのスキャン、レポートのドリルダウン | カラムストアMV + クエリのリライト(オプション) | スキャンする列が全列より少ない場合、効果が顕著です | シナリオ1:運用分析とレポートのドリルダウン |
| 低遅延オンラインクエリ(クエリトリガーによる補正計算) | ENABLE ON QUERY COMPUTATION |
読み取り時の計算により更新時の処理を簡略化し、ホットクエリモデルに適しています | シナリオ2:リアルタイム指標加工パイプライン |
| SQLの透過的加速(業務SQLの変更を最小限に抑える) | ENABLE QUERY REWRITE + インデックス/集計口径の整合性 |
リライトのマッチングルールに依存するため、固定の分析テンプレートに適しています | シナリオ2:リアルタイム指標加工パイプライン |
| ファイルインレイク後の周期的ロード | 外部テーブル + REFRESH COMPLETE |
データソースはファイルから取得し、まずオフラインで同期してからクエリを実行します | シナリオ3:レイクハウスへのデータ取り込みと周期的ロード |
推奨される実践的な手順は以下の通りです:
- まず、集計基準と更新戦略を定義する:「分単位の増分」か「クエリ時のリアルタイム計算」かを明確にします。
- 次にリフレッシュメカニズムを定める:FASTが条件を満たすか優先的に評価し、満たさない場合にCOMPLETEを使用します。
- 最後に、クエリ側の最適化を行う:必要に応じて、カラムストア、インデックス、およびQUERY REWRITEを段階的に導入し、一度に多くの変数を導入することを避けます。
注意
リアルタイムデータウェアハウスは「すべてのクエリがリアルタイムで更新される」と同義ではありません。業務上分単位の遅延が許容される場合は、優先的にFAST + スケジューリングを採用します。低遅延が必須であり、読み取り時のオーバーヘッドを許容できる場合にのみ、ENABLE ON QUERY COMPUTATIONを導入します。
入門実践:注文テーブルにおけるフルリフレッシュと増分リフレッシュ
以下では、業務データベースで一般的な 注文テーブル を例に説明します。これは、デフォルトのフルメンテナンス のマテリアライズドビュー、FAST の増分メンテナンス、手動リフレッシュ、定時スケジューリング の基本的な使い方を示しています(マテリアライズドビューのリフレッシュと一致しています)。
テーブル作成、データ生成、フルマテリアライズドビューの作成
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
item_id INT,
item_count INT,
item_price INT,
region VARCHAR(100)
);
INSERT INTO orders VALUES
(1, 10001, 1, 20, 100, 'HZ'),
(2, 10002, 1, 10, 150, 'BJ'),
(3, 10001, 2, 50, 50, 'SH');
CREATE MATERIALIZED VIEW mv1
AS
SELECT region, SUM(item_count * item_price) AS sum_price
FROM orders
GROUP BY region;
SELECT * FROM mv1;
マテリアライズドビューを作成する際には、まず 初回マテリアライズ が行われます。明確に更新戦略を宣言していない場合、通常は 手動でのフル更新 が必要であり、これによりベーステーブルとの一貫性を維持できます。
手動フルリフレッシュ(DBMS_MVIEW.REFRESH)
ベーステーブルへの書き込みを続けると、マテリアライズドビューの結果は自動的に変更されません。更新をトリガーする必要があります:
INSERT INTO orders VALUES
(4, 10002, 2, 10, 100, 'SH'),
(5, 10003, 1, 2, 20, 'HZ');
SELECT * FROM mv1;
実行結果:
+--------+-----------+
| region | sum_price |
+--------+-----------+
| HZ | 2000 |
| BJ | 1500 |
| SH | 2500 |
+--------+-----------+
3 rows in set
マテリアライズドビューの結果が自動的に変更されていないことが確認できます。以下のSQLを実行して更新をトリガーする必要があります:
CALL DBMS_MVIEW.REFRESH('mv1', 'c', refresh_parallel => 2);
SELECT * FROM mv1;
実行結果:
+--------+-----------+
| region | sum_price |
+--------+-----------+
| HZ | 2040 |
| BJ | 1500 |
| SH | 3500 |
+--------+-----------+
3 rows in set
'c' は complete 完全更新を表します。refresh_parallel などのパラメータについては DBMS_MVIEW.REFRESH を参照してください。
更新の実行状況を確認できます(例):
SELECT MVIEWS, METHOD, START_TIME, END_TIME
FROM oceanbase.DBA_MVREF_RUN_STATS;
削除後は増分更新に切り替える
DROP MATERIALIZED VIEW mv1;
CREATE MATERIALIZED VIEW mv1(region, c, sum_price, cnt_price)
REFRESH FAST
ON DEMAND START WITH sysdate() NEXT sysdate() + INTERVAL 5 MINUTE
AS SELECT
region,
SUM(item_count * item_price) AS sum_price
FROM orders
GROUP BY region;
説明
V4.4.2 BP2 より前のバージョンを使用する場合、マテリアライズドビュー定義における集約関数は、SELECT 句に依存列を含める必要があります。詳細については、マテリアライズドビューの更新(MySQLモード) および マテリアライズドビューの更新(Oracleモード) を参照してください。
新規注文を挿入した後、手動で増分更新 を行います:
データを挿入します。
INSERT INTO orders VALUES (6, 10001, 3, 30, 70, 'HZ');手動で更新します。
CALL DBMS_MVIEW.REFRESH('mv1', 'f');マテリアライズドビューのデータを確認します。
SELECT region, sum_price FROM mv1;作成時に
START WITH ... NEXT ...を設定している場合は、DBA_SCHEDULER_JOBSでバックグラウンド更新タスクも確認できます(具体的なフィールドは現在のバージョンのディクショナリ説明に準じます)。
オブジェクトのクリーンアップ順序
マテリアライズドビューとベーステーブルを削除する際は、MVを先に削除し、次にベーステーブルを削除する ことに注意してください。
DROP MATERIALIZED VIEW mv1;
DROP TABLE orders;
シナリオ1:運用分析とレポートクエリ
運用分析およびレポートクエリのシナリオでは、一般的な課題として明細テーブルの列数が多く、スキャン範囲が広く、クエリ条件が頻繁に変更されることが挙げられます。
このようなシナリオは通常、読み取り処理が主体となるため、カラムストアマテリアライズドビューを活用して不要な列のスキャンを削減し、必要に応じてインデックスやクエリのリライトを組み合わせて、クエリパフォーマンスをさらに最適化してください。
このセクションでは、簡単な例を通じて、カラムストアマテリアライズドビューを使用してワイドテーブルのクエリと多次元分析をサポートする方法を説明します。
CREATE TABLE IF NOT EXISTS tbl1 (col1 INT PRIMARY KEY, col2 VARCHAR(20), col3 INT);
CREATE MATERIALIZED VIEW mv_ec_tbl1
WITH COLUMN GROUP(each column)
AS SELECT *
FROM tbl1;
クエリのリライトを併用する場合、通常はリライト後の条件がマテリアライズドビュー上のインデックスを利用できることを保証する必要があります(ルールについては マテリアライズドビューによるクエリのリライト を参照):
CREATE INDEX idx1_mv_ec_tbl1 ON mv_ec_tbl1(col1);
シナリオ2:リアルタイム指標の計算とクエリ
リアルタイムメトリクスシナリオでは、階層集計、増分メンテナンス、低遅延クエリ、および業務SQLの変更を最小限に抑えることが一般的な要件です。
このようなシナリオは通常、単一の機能ではカバーできず、業務の時間的要件に応じて、FAST更新、リアルタイムマテリアライズドビュー、クエリのリライトなどの機能を組み合わせて使用する必要があります。
増分更新(FAST)
業務では更新効率が重要であり、毎回すべてのデータを再計算することよりも、FAST 更新の使用を検討できます。この方法はベーステーブルの変更を記録し、更新時には可能な限り増分データのみを処理します。
CREATE TABLE IF NOT EXISTS tbl5 (col1 INT PRIMARY KEY, col2 INT, col3 INT);
REFRESH FAST
AS SELECT col2, COUNT(*) cnt, COUNT(col3) cnt_col3, SUM(col3) sum_col3
AS SELECT
col2,
SUM(col3) sum_col3
GROUP BY col2;
GROUP BY col2;
説明
V4.4.2 BP2 より前のバージョンを使用している場合、マテリアライズドビュー定義内の集約関数は SELECT 句に依存列を含める必要があります。詳細については、マテリアライズドビューの更新(MySQLモード) および マテリアライズドビューの更新(Oracleモード) を参照してください。
CALL DBMS_MVIEW.REFRESH('mv_tbl5', 'c');
CALL DBMS_MVIEW.REFRESH('mv_tbl5', 'c');
リアルタイムマテリアライズドビュー
シナリオによっては、クエリの即時性に対する要求が高く、リアルタイムに近い結果を求める一方で、頻繁な自発的更新には適さない場合があります。このような場合、実際のニーズに基づいてリアルタイムマテリアライズドビューの使用を評価し、クエリ時の計算によるデータの鮮度向上とのトレードオフを検討できます。
CREATE TABLE IF NOT EXISTS tbl2(col1 INT, col2 INT, col3 INT);
ENABLE ON QUERY COMPUTATION
AS SELECT col1, COUNT(*) AS cnt
AS SELECT
col1
GROUP BY col1;
GROUP BY col1;
説明
V4.4.2 BP2 より前のバージョンを使用している場合、マテリアライズドビュー定義内の集約関数は SELECT 句に依存列を含める必要があります。詳細については、マテリアライズドビューの更新(MySQLモード) および マテリアライズドビューの更新(Oracleモード) を参照してください。
クエリのリライト(ENABLE QUERY REWRITE)
業務SQLの変更を最小限に抑えつつ、オプティマイザーにマテリアライズドビューの結果を自動的に使用させたい場合は、クエリのリライト機能を活用できます。クエリのリライトは固定された分析シナリオに適していますが、リライトが成功するかどうかは、クエリ条件とマテリアライズドビュー定義が一致するかどうかに依存します。
CREATE TABLE IF NOT EXISTS test_tbl2 (col1 INT, col2 INT, col3 INT);
CREATE TABLE IF NOT EXISTS test_tbl2 (col1 INT, col2 INT, col3 INT);
ENABLE QUERY REWRITE
AS SELECT t1.col1 col1, t1.col2 t1col2, t1.col3 t1col3, t2.col2 t2col2, t2.col3 t2col3
AS SELECT
t1.col1 col1,
t1.col2 t1col2,
t1.col3 t1col3,
t2.col2 t2col2,
t2.col3 t2col3
WHERE t1.col1 = t2.col1;
WHERE t1.col1 = t2.col1;
SET query_rewrite_enabled = 'force';
SELECT
COUNT(*),
test_tbl1.col1 col1
WHERE test_tbl1.col1 = test_tbl2.col1 AND test_tbl2.col2 > 10
WHERE test_tbl1.col1 = test_tbl2.col1
AND test_tbl2.col2 > 10
GROUP BY col1;
シナリオ3:ファイルデータのインポートと定期的なリフレッシュ
データがオンラインの業務テーブルではなくファイルから取得される場合、まず外部テーブルを使用してファイルデータを読み取り、その後外部テーブルに基づいてフルリフレッシュマテリアライズドビューを作成します。この方法は、定期的な更新、オフライン同期後のクエリ、およびレイクハウス統合シナリオにおける定期的なデータ取り込み要件に適しています。
V4.3.5 BP2 以降では、外部テーブルをベーステーブルとして フルリフレッシュ マテリアライズドビューを作成できるようになりました。事前に secure_file_priv を設定し、外部ファイルを準備しておく必要があります。また、CREATE EXTERNAL TABLE を実行する必要があります(手順の詳細については、マテリアライズドビューの作成 — 外部テーブルに基づく作成を参照してください)。
id INT,
name VARCHAR(50),
c_date DATE
)
LOCATION = '/home/admin'
FORMAT = (
TYPE = 'CSV'
FIELD_DELIMITER = ','
FIELD_OPTIONALLY_ENCLOSED_BY = '\''
)
PATTERN = 'ext_tbl1.csv';
PATTERN = 'ext_tbl1.csv';
REFRESH COMPLETE
AS SELECT * FROM ext_tbl1;
AS SELECT * FROM ext_tbl1;
外部テーブルのその他の実践例については、外部テーブルを使用した INSERT INTO SELECT によるインポートおよび外部テーブルの概要を参照してください。