データ更新概要
今日のデータドリブンな意思決定環境において、データの「鮮度」は、企業が激しい市場競争で差別化を図るための中核的な競争優位性となっています。従来のT+1データ処理モデルは、その固有の遅延により、現代ビジネスの厳格なリアルタイム要件をもはや満たすことができません。ビジネスデータベースとデータウェアハウス間のミリ秒レベルの同期、運用戦略の動的調整、意思決定の精度を確保するための数秒以内での誤ったデータの修正など、どれにおいても堅牢なリアルタイムデータ更新機能が重要です。
Apache Dorisは、現代的なリアルタイム分析データベースとして、究極のデータ鮮度を提供することをコア設計目標の一つとしています。その強力なデータモデルと柔軟な更新メカニズムにより、データ分析の遅延を日レベル・時間レベルから秒レベルまで短縮することに成功し、ユーザーがリアルタイムで機敏なビジネス意思決定ループを構築するための強固な基盤を提供しています。
このドキュメントは、Apache Dorisのデータ更新機能を体系的に説明する公式ガイドとして機能し、そのコア原理、多様な更新・削除方法、典型的な適用シナリオ、異なるデプロイモードでのパフォーマンスベストプラクティスを網羅し、Dorisのデータ更新機能を包括的に習得し効率的に活用することを支援することを目的としています。
1. コア概念:テーブルモデルと更新メカニズム
Dorisにおいて、データテーブルのData Modelは、そのデータ構成と更新動作を決定します。異なるビジネスシナリオをサポートするため、DorisはUnique Key Model、Aggregate Key Model、Duplicate Key Modelの3つのテーブルモデルを提供しています。この中で、Unique Key Modelは複雑で高頻度なデータ更新を実装するためのコアです。
1.1. テーブルモデル概要
| テーブルモデル | 主要機能 | 更新機能 | 使用例 |
|---|---|---|---|
| Unique Key Model | リアルタイム更新のために構築。各データ行は一意のPrimary Keyで識別され、行レベルのUPSERT(アップデート/Insert)と部分列更新をサポート。 | 最強、すべての更新・削除方法をサポート。 | 注文ステータス更新、リアルタイムユーザータグ計算、CDCデータ同期、その他頻繁でリアルタイムな変更が必要なシナリオ。 |
| Aggregate Key Model | 指定されたKey列に基づいてデータを事前集約。同じKeyを持つ行について、Value列は定義された集約関数(SUM、MAX、MIN、REPLACEなど)に従ってマージされる。 | 限定的、Key列に基づくREPLACEスタイルの更新と削除をサポート。 | リアルタイム要約統計が必要なシナリオ、リアルタイムレポート、広告クリック統計など。 |
| Duplicate Key Model | データは追加のみの書き込みをサポートし、重複排除や集約操作は行わない。同一のデータ行でも保持される。 | 限定的、DELETE文による条件付き削除のみサポート。 | ログ収集、ユーザー行動追跡、その他更新なしで追加のみが必要なシナリオ。 |
1.2. データ更新方法
Dorisは2つの主要なデータ更新方法カテゴリを提供します:データロードによる更新とDML文による更新。
1.2.1. Load(UPSERT)による更新
これはDorisの推奨される高パフォーマンス、高同時実行性更新方法で、主にUnique Key Modelを対象としています。すべてのロード方法(Stream Load、Broker Load、Routine Load、INSERT INTO)は、UPSERTセマンティクスを自然にサポートしています。新しいデータがロードされる際、そのプライマリキーが既に存在する場合、Dorisは古い行データを新しい行データで上書きし、プライマリキーが存在しない場合は新しい行を挿入します。

1.2.2. UPDATE DML文による更新
Dorisは標準SQL UPDATE文をサポートし、ユーザーがWHERE句で指定された条件に基づいてデータを更新できます。この方法は非常に柔軟で、テーブル間結合更新などの複雑な更新ロジックをサポートします。

-- Simple update
UPDATE user_profiles SET age = age + 1 WHERE user_id = 1;
-- Cross-table join update
UPDATE sales_records t1
SET t1.user_name = t2.name
FROM user_profiles t2
WHERE t1.user_id = t2.user_id;
注意: UPDATE文の実行プロセスは、まず条件に一致するデータをスキャンし、次に更新されたデータをテーブルに書き戻すことを含みます。これは低頻度のバッチ更新タスクに適しています。同じプライマリキーに関わる同時UPDATE操作はデータの分離を保証できないため、UPDATE文での高並行操作は推奨されません。
1.2.3. INSERT INTO SELECT DML文による更新
DorisはデフォルトでUPSERT セマンティクスを提供するため、INSERT INTO SELECTを使用することでUPDATEと同様の更新効果を実現することもできます。
1.3. データ削除方法
更新と同様に、DorisはロードとDML文の両方を通じてデータの削除をサポートします。
1.3.1. ロードによるマーク削除
これは効率的なバッチ削除方法であり、主にUnique Key Modelで使用されます。ユーザーはデータをロードする際に特別な隠しカラムDORIS_DELETE_SIGNを追加できます。ある行のこのカラムの値が1またはtrueの場合、Dorisはそのプライマリキーに対応するデータ行を削除済みとしてマークします(delete signの原理については後で詳しく説明します)。
// Stream Load load data, delete row with user_id = 2
// curl --location-trusted -u user:passwd -H "columns:user_id, __DORIS_DELETE_SIGN__" -T delete.json http://fe_host:8030/api/db_name/table_name/_stream_load
// delete.json content
[
{"user_id": 2, "__DORIS_DELETE_SIGN__": "1"}
]
1.3.2. DELETE DML文による削除
Dorisは標準SQL DELETE文をサポートしており、WHERE条件に基づいてデータを削除できます。
- Unique Key Model:
DELETE文は条件に一致する行の主キーを削除マークで書き換えます。そのため、そのパフォーマンスは削除するデータ量に比例します。Unique Key ModelでのDELETE文の実行原理はUPDATE文と非常に似ており、まずクエリを通じて削除するデータを読み取り、次に削除マークを付けて再度書き込みます。UPDATE文と比較して、DELETE文はKeyカラムと削除マークカラムのみを書き込む必要があるため、比較的軽量です。 - Duplicate/Aggregate Models:
DELETE文はdelete predicateを記録することで実装されます。クエリ時に、このpredicateはランタイムフィルタとして機能し、削除されたデータを除外します。そのため、DELETE操作自体は非常に高速で、削除されるデータ量にほぼ依存しません。ただし、Duplicate/Aggregate Modelでの高頻度のDELETE操作は多くのランタイムフィルタを蓄積し、後続のクエリパフォーマンスに深刻な影響を与えることに注意してください。
DELETE FROM user_profiles WHERE last_login < '2022-01-01';
次の表は、削除のためのDML文の使用に関する簡潔な要約を提供しています:
| Unique Key Model | Aggregate Model | Duplicate Model | |
|---|---|---|---|
| 実装方式 | Delete Sign | Delete Predicate | Delete Predicate |
| 制限事項 | なし | Keyカラムのみ削除条件 | なし |
| 削除パフォーマンス | 中程度 | 高速 | 高速 |
2. Unique Key Modelの詳細解説:原理と実装
Unique Key ModelはDorisの高性能リアルタイム更新の基盤です。そのパフォーマンスを最大限に活用するためには、内部動作原理の理解が重要です。
2.1. Merge-on-Write (MoW) vs. Merge-on-Read (MoR)
Unique Key Modelには2つのデータマージ戦略があります:Merge-on-Write (MoW)とMerge-on-Read (MoR)です。Doris 2.1以降、MoWがデフォルトかつ推奨の実装となっています。
| 機能 | Merge-on-Write (MoW) | Merge-on-Read (MoR) - (レガシー) |
|---|---|---|
| コアコンセプト | データ書き込み時にデータの重複排除とマージを完了し、ストレージ内でプライマリキーごとに最新レコードのみが保持されることを保証します。 | データ書き込み時に複数バージョンを保持し、クエリ実行時にリアルタイムマージを行い最新バージョンを返します。 |
| クエリパフォーマンス | 極めて高速。クエリ時に追加のマージ操作が不要で、パフォーマンスは更新のないdetailテーブルに近づきます。 | 劣悪。クエリ時にデータマージが必要で、MoWより約3-10倍時間がかかり、より多くのCPUとメモリを消費します。 |
| 書き込みパフォーマンス | 書き込み時にマージオーバーヘッドがあり、MoRと比較してパフォーマンス低下があります(小バッチで約10-20%、大バッチで30-50%)。 | 高速な書き込み速度で、detailテーブルに近づきます。 |
| リソース消費 | 書き込み時とバックグラウンドCompaction時により多くのCPUとメモリを消費します。 | クエリ時により多くのCPUとメモリを消費します。 |
| 使用ケース | ほとんどのリアルタイム更新シナリオ。特に読み取り重視、書き込み軽量のビジネスに適し、究極のクエリ分析パフォーマンスを提供します。 | 書き込み重視、読み取り軽量のシナリオに適していますが、もはや主流の推奨ではありません。 |
MoWメカニズムは書き込みフェーズでの小さなコストと引き換えに、クエリパフォーマンスの大幅な向上を実現し、OLAPシステムの「読み取り重視、書き込み軽量」の特性と完全に一致しています。
2.2. 条件付き更新(Sequence Column)
分散システムでは、順序通りでないデータの到着は一般的な問題です。例えば、注文ステータスが順次「支払済み」と「配送済み」に変更されますが、ネットワーク遅延により、「配送済み」を表すデータが「支払済み」を表すデータよりも先にDorisに到着する可能性があります。
この問題を解決するため、DorisはSequence Columnメカニズムを導入しています。ユーザーはテーブル作成時に列(通常はタイムスタンプまたはバージョン番号)をSequence columnとして指定できます。同じプライマリキーのデータを処理する際、DorisはそれらのSequence columnの値を比較し、常に最大のSequence値を持つ行を保持することで、データが順序通りでない状態で到着してもデータの結果整合性を保証します。
CREATE TABLE order_status (
order_id BIGINT,
status_name STRING,
update_time DATETIME
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id)
PROPERTIES (
"function_column.sequence_col" = "update_time" -- Specify update_time as Sequence column
);
-- 1. Write "Shipped" record (larger update_time)
-- {"order_id": 1001, "status_name": "Shipped", "update_time": "2023-10-26 12:00:00"}
-- 2. Write "Paid" record (smaller update_time, arrives later)
-- {"order_id": 1001, "status_name": "Paid", "update_time": "2023-10-26 11:00:00"}
-- Final query result, retains record with largest update_time
-- order_id: 1001, status_name: "Shipped", update_time: "2023-10-26 12:00:00"
2.3. 削除メカニズム(DORIS_DELETE_SIGN)のワークフロー
DORIS_DELETE_SIGNの動作原理は「論理マーキング、バックグラウンドクリーンアップ」と要約できます。
- 削除実行: ユーザーがloadまたは
DELETE文でデータを削除する際、Dorisは物理ファイルからデータを即座に削除しません。代わりに、削除対象のプライマリキーに対して新しいレコードを書き込み、DORIS_DELETE_SIGN列を1とマークします。 - クエリフィルタリング: ユーザーがデータをクエリする際、Dorisは自動的にクエリプランに
WHERE DORIS_DELETE_SIGN = 0のフィルタ条件を追加し、削除マークが付けられたすべてのデータをクエリ結果から非表示にします。 - バックグラウンドCompaction: DorisのバックグラウンドCompactionプロセスは定期的にデータをスキャンします。通常レコードと削除マークレコードの両方を持つプライマリキーを発見すると、マージプロセス中に両方のレコードを物理的に削除し、最終的にストレージスペースを解放します。
このメカニズムにより、削除操作への迅速な応答を保証しながら、バックグラウンドタスクを通じて物理クリーンアップを非同期的に完了し、オンラインビジネスへのパフォーマンス影響を回避します。
以下の図はDORIS_DELETE_SIGNの動作方法を示しています:

2.4 部分列更新
バージョン2.0以降、DorisはUnique Key Model(MoW)において強力な部分列更新機能をサポートしています。データロード時、ユーザーはプライマリキーと更新対象の列のみを提供すればよく、提供されていない列は元の値を変更せずに維持します。これにより、ワイドテーブル結合やリアルタイムタグ更新などのシナリオにおけるETLプロセスが大幅に簡素化されます。
この機能を有効にするには、Unique Key Modelテーブル作成時にMerge-on-Write(MoW)モードを有効にする必要があります。INSERT INTOの場合、セッション変数enable_unique_key_partial_updateをtrueに設定して部分列更新を有効にし、Stream Loadやその他のインポート方法の場合、partial_columnsパラメータを設定して部分列更新を有効にします。
CREATE TABLE user_profiles (
user_id BIGINT,
name STRING,
age INT,
last_login DATETIME
)
UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id)
PROPERTIES (
"enable_unique_key_merge_on_write" = "true"
);
-- Initial data
-- user_id: 1, name: 'Alice', age: 30, last_login: '2023-10-01 10:00:00'
-- load partial update data through Stream Load, only updating age and last_login
-- {"user_id": 1, "age": 31, "last_login": "2023-10-26 18:00:00"}
-- Updated data
-- user_id: 1, name: 'Alice', age: 31, last_login: '2023-10-26 18:00:00'
部分列更新の原理概要
従来のOLTPデータベースとは異なり、Dorisの部分列更新はインプレースデータ更新ではありません。Dorisでより良い書き込みスループットとクエリパフォーマンスを実現するため、Unique Key Modelsの部分列更新は「ロード時欠損フィールド補完後の全行書き込み」実装アプローチを採用しています。
そのため、Dorisの部分列更新を使用すると**「読み取り増幅」と「書き込み増幅」**効果があります。例えば、100列の幅広いテーブルで10フィールドを更新する場合、Dorisは書き込みプロセス中に欠損している90フィールドを補完する必要があります。各フィールドが同様のサイズと仮定すると、1MBの10フィールド更新では、Dorisシステム内で約9MBのデータ読み取り(欠損フィールドの補完)と10MBのデータ書き込み(完全な行を新しいファイルに書き込み)が生成され、約9倍の読み取り増幅と10倍の書き込み増幅が発生します。
部分列更新パフォーマンス推奨事項
部分列更新における読み取りおよび書き込み増幅により、Dorisは列指向ストレージシステムであるため、データ読み取りプロセスで大量のランダムI/Oが発生する可能性があり、ストレージから高いランダム読み取りIOPSが要求されます。従来の機械式ディスクはランダムI/Oに大きなボトルネックがあるため、高頻度書き込みで部分列更新機能を使用したい場合は、SSDドライブ、可能であればNVMeインターフェースを推奨します。これにより最適なランダムI/Oサポートが提供されます。
さらに、テーブルが非常に幅広い場合は、ランダムI/Oを削減するために行ストレージの有効化も推奨します。行ストレージを有効にすると、Dorisは列指向ストレージと並行して行ベースデータの追加コピーを保存します。行ベースデータは各行を連続して保存するため、単一のI/O操作で行全体を読み取ることができます(列指向ストレージでは、すべての欠損フィールドを読み取るためにN回のI/O操作が必要です。例えば、前述の100列幅広いテーブルで10列を更新する場合、すべてのフィールドを読み取るために行あたり90回のI/O操作が必要です)。
3. 典型的なアプリケーションシナリオ
Dorisの強力なデータ更新機能により、さまざまな要求の厳しいリアルタイム分析シナリオを処理できます。
3.1. CDCリアルタイムデータ同期
Flink CDCなどのツールを通じて上流ビジネスデータベース(MySQL、PostgreSQL、Oracleなど)から変更データ(Binlog)をキャプチャし、Doris Unique Key Modelテーブルにリアルタイムで書き込むことは、リアルタイムデータウェアハウス構築の最も典型的なシナリオです。
- 全データベース同期: Flink Doris ConnectorはFlink CDCを内部統合し、手動のテーブル作成およびフィールドマッピング設定なしに、上流データベースからDorisへの自動化されたエンドツーエンド全データベース同期を可能にします。
- 一貫性の保証: Unique Key Modelの
UPSERT機能を利用して上流のINSERTおよびUPDATE操作を処理し、DORIS_DELETE_SIGNを使用してDELETE操作を処理し、Sequence列(Binlogのタイムスタンプなど)と組み合わせて順序外データを処理することで、上流データベース状態を完璧に複製し、ミリ秒レベルのデータ同期レイテンシを実現します。

3.2. リアルタイム幅広いテーブル結合
多くの分析シナリオでは、異なるビジネスシステムからのデータをユーザー幅広いテーブルや製品幅広いテーブルに結合する必要があります。従来のアプローチでは、定期的(T+1)結合にオフラインETLタスク(SparkやHiveなど)を使用しますが、これはリアルタイム性能が悪く、メンテナンスコストが高くなります。または、リアルタイム幅広いテーブル結合計算にFlinkを使用し、結合されたデータをデータベースに書き込む場合、通常大幅な計算リソースが必要です。
Dorisの部分列更新機能を使用することで、このプロセスを大幅に簡素化できます:
- DorisにUnique Key Model幅広いテーブルを作成します。
- 異なるソース(ユーザー基本情報、ユーザー行動データ、取引データなど)からのデータストリームを、Stream LoadまたはRoutine Loadを通じてこの幅広いテーブルにリアルタイムで書き込みます。
- 各データストリームは関連するフィールドのみを更新します。例えば、ユーザー行動データストリームは
page_view_count、last_login_timeなどのフィールドのみを更新し、取引データストリームはtotal_orders、total_amountなどのフィールドのみを更新します。
このアプローチは、幅広いテーブル構築をオフラインETLからリアルタイムストリーム処理に変換してデータの新鮮さを大幅に向上させるだけでなく、変更された列のみを書き込むことでI/Oオーバーヘッドを削減し、書き込みパフォーマンスを向上させます。
4. ベストプラクティス
これらのベストプラクティスに従うことで、Dorisのデータ更新機能をより安定して効率的に使用できます。
- ロード更新を優先: 高頻度で大容量の更新操作では、
UPDATEDMLステートメントよりもStream LoadやRoutine Loadなどのロード方法を優先します。 - バッチ書き込み: 個別の高頻度書き込み(> 100 TPSなど)に
INSERT INTOステートメントの使用を避けます。各INSERTにはトランザクションオーバーヘッドが発生するためです。必要な場合は、Group Commit機能の有効化を検討して、複数の小さなバッチコミットを1つの大きなトランザクションにマージします。 - 高頻度
DELETEの慎重な使用: Duplicate およびAggregateモデルでは、クエリパフォーマンスの低下を防ぐため、高頻度のDELETE操作を避けます。 - パーティションデータ削除に
TRUNCATE PARTITIONを使用: パーティション全体のデータを削除する必要がある場合は、DELETEよりもはるかに効率的なTRUNCATE PARTITIONを使用します。 UPDATEの順次実行: 同じデータ行に影響を与える可能性のあるUPDATEタスクの同時実行を避けます。
結論
Apache Dorisは、Unique Key Modelを中心とした強力で柔軟かつ効率的なデータ更新機能により、データの新鮮さにおける従来のOLAPシステムのボトルネックを真に突破しています。UPSERTと部分列更新を実装する高性能ロードから、順序外データの一貫性を保証するSequence列の使用まで、Dorisはエンドツーエンドリアルタイム分析アプリケーション構築のための完全なソリューションを提供します。
その核心原理を深く理解し、異なる更新方法の適用シナリオを習得し、この文書で提供されるベストプラクティスに従うことで、Dorisのポテンシャルを完全に引き出し、リアルタイムデータを真にビジネス成長を推進する強力なエンジンにすることができます。