メインコンテンツまでスキップ
に最終更新

データの更新と削除

要点 Apache Doris は、トランザクションデータベースと同じように SQL の UPDATE と DELETE に対応します。さらに、ストリーミングデータロードからの部分カラム upsert、述語を指定した一括削除、アトミックなパーティション切り替えも利用できます。Unique Key テーブルでは、Merge-on-Write エンジンが、読み取り時にバージョンをマージする代わりに、書き込み時に削除された行を rowset ごとの bitmap に記録するため、クエリのレイテンシーを低く抑えられます。Merge-on-Write はバージョン 2.1 から Unique Key のデフォルトになりました。

Apache Doris のデータ更新と削除:SQL UPDATE、述語 DELETE、部分カラム upsert、アトミックなパーティション切り替えを、Unique Key テーブルの Merge-on-Write が支えます。

Apache Doris でデータを更新・削除する理由​

Apache Doris のデータ更新・削除は、分析エンジンでトランザクションを伴う行単位の変更を可能にします。CDC、GDPR に基づく消去、単発の修正のたびに、パーティション全体を書き直す必要はありません。多くの分析エンジンは、データウェアハウスには追記しかしないという前提で作られました。しかし、CDC や GDPR への対応が必要になり、運用データには誤りがあるというありふれた現実にも直面しました。パーティションを書き直さなければ一行の誤りも直せないウェアハウスでは、遅れて届く修正が毎回運用チケットになります。

  • Flink CDC ジョブが MySQL を監視しており、各行の更新を数秒以内に反映する必要があります。
  • ユーザーが GDPR に基づく削除を求めています。「次の compaction 後に消える」ではなく、ウェアハウスから削除する必要があります。
  • 10 billion行規模のファクトテーブルにあるたった一行の入力ミスが原因で、レポートの数値が誤っています。

Apache Doris は、これらすべてに標準の SQL 操作で対応します。UPDATE、DELETE FROM ... WHERE、Stream Load からの部分カラム upsert、一括クリーンアップ向けの TRUNCATE やアトミックなパーティション置換を利用できます。テーブルが小さい必要はなく、後から書き直しジョブをスケジュールする必要もありません。

Apache Doris のデータ更新と削除とは​

Apache Doris のデータ更新と削除は、UPDATE SQL、述語 DELETE、部分カラム upsert、パーティション切り替えという四つの操作で構成され、Unique Key テーブルの Merge-on-Write エンジンが支えています。行単位の UPDATE SQL は Unique Key テーブルで使用でき、述語を指定する DELETE FROM ... WHERE はどのテーブルでも使用できます。部分カラム upsert はデータ取り込み時に指定します(Stream Load ヘッダーの partial_columns: true、または対応するセッション変数を使用)。パーティション単位の操作には、TRUNCATE PARTITION と一時パーティションのアトミックな置換があります。内部では、Unique Key モデルが Merge-on-Write(MoW)を使用し、削除と更新をクエリ時ではなく書き込み時に反映します。MoW は 1.2 で導入され、2.1 で Unique Key のデフォルトになりました。

主な用語

  • Unique Key model:主キーごとに一行だけ保持するテーブルモデル。UPDATE とバッチ upsert に必要です。
  • Merge-on-Write (MoW):Apache Doris が書き込み時に新しい各キーを既存データから探し、古い行を delete bitmap に記録して、新しい行を新しい rowset に書き込む方式です。
  • Delete bitmap:クエリで読み飛ばす行 ID を rowset ごとに記録する bitmap。読み取り時にキーごとのバージョンをマージする処理に代わります。
  • Partial column update:一部のカラムだけを変更する書き込み。Apache Doris は既存行から指定されていないカラムの値を読み取り、完全な行を書き戻します。
  • Sequence column(function_column.sequence_col):順序どおりに届かない書き込みがあったとき、同じキーのどのバージョンを採用するかを MoW に示す、ユーザー指定のカラムです。
  • __DORIS_DELETE_SIGN__:どのデータロード経路からでも、値を 1 に設定して行を論理削除できる隠しカラムです。

Apache Doris のデータ更新と削除の仕組み​

Unique Key MoW テーブルでのデータ更新と削除は、計画と読み取り、キーの検索、古い行の delete bitmap のビット設定、新しい rowset への新しい行の書き込み、新しいバージョンの公開という五段階で進みます。

Unique Key MoW テーブルに対する UPDATE を例に見てみましょう。

  1. 計画と読み取り。 FE が文を解析し、WHERE 述語を解決して、BE レプリカ間に読み取りを振り分けます。部分カラム書き込みでは、BE が対象キーごとに指定されていないカラムの値も取得します。
  2. キーの検索。 各 BE は rowset ごとのメモリ内主キーインデックスを参照し、対象キーが現在どの rowset のどの行 ID にあるかを調べます。
  3. 古い行の記録。 対象キーを含む各 rowset で、対応する行 ID のビットを delete bitmap で立てます。古い行は compaction で回収されるまでディスクに残ります。
  4. 新しい行の書き込み。 新しい値と、部分更新のために Apache Doris が読み取った変更のないカラムの値を、次のバージョン番号を持つ新しい rowset に書き込みます。
  5. 公開。 トランザクションがコミットされ、新しいバージョンが参照可能になります。それ以降のクエリは、マージされた delete bitmap に基づいて行を除外します。古いデータは compaction 時に回収されます。

DELETE FROM ... WHERE も、書き込み段階を除けば同じ流れです。Aggregate または Duplicate テーブルでは、Apache Doris は代わりに述語を tablet のメタデータに記録し、クエリが読み取り時に適用します。

クイックスタート​

CREATE TABLE orders (
order_id BIGINT,
status VARCHAR(20),
amount DECIMAL(10, 2),
updated DATETIME
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 4
PROPERTIES ("function_column.sequence_col" = "updated");

INSERT INTO orders VALUES
(1, 'created', 99.50, '2026-05-08 10:00:00'),
(2, 'created', 149.00, '2026-05-08 10:01:00');

UPDATE orders SET status = 'shipped', updated = NOW() WHERE order_id = 1;
DELETE FROM orders WHERE order_id = 2;

期待される結果

+----------+---------+--------+---------------------+
| order_id | status | amount | updated |
+----------+---------+--------+---------------------+
| 1 | shipped | 99.50 | 2026-05-08 11:42:31 |
+----------+---------+--------+---------------------+

注文1の行はその場で書き換えられ、注文2の行は削除されています。function_column.sequence_col プロパティは、順序どおりに届かない書き込みからテーブルを守ります。既存行より古い updated タイムスタンプを持つ CDC イベントは、より新しいイベントの後から届いても既存行に優先しません。

Apache Doris のデータ更新と削除を使う場面​

Apache Doris のデータ更新と削除は、Unique Key テーブルへの CDC upsert、ワイドテーブルで頻繁に変わるカラムの更新、GDPR 対応の行単位の削除、アトミックなバックフィルの切り替え、複数ストリームからのワイドテーブル構築に適しています。一方、Aggregate または Duplicate テーブルでの UPDATE、密なループで実行する単一行の更新、主キーの変更、パーティション置換で一度に処理できる大量行への述語 DELETE には適していません。

適した用途

  • ソースの主キーを Apache Doris のキーとして使い、Unique Key テーブルに upsert する Flink や Spark の CDC パイプライン。
  • 部分カラム Stream Load による、ワイドテーブルで頻繁に変わるカラム(注文ステータス、最終アクセス日時、現在の残高)の更新。
  • 追記専用の Duplicate テーブルも含め、ユーザー ID を指定して行単位で削除する GDPR 対応。
  • ALTER TABLE ... REPLACE PARTITION で修正済みパーティションをアトミックに切り替えるバックフィル。
  • 各上流システムが担当するカラム群だけを書き込む、複数ストリームからのワイドテーブル構築。

適さない用途

  • Aggregate または Duplicate テーブルでの UPDATE。文は拒否されます。データ取り込みによって再ロードするか(Aggregate では値の上書きに REPLACE_IF_NOT_NULL を使用)、テーブルモデルを変更してください。
  • 密なループで行う高頻度の単一行 UPDATE。各文が個別のトランザクションとなり、コミットのオーバーヘッドが支配的になります。代わりに partial_columns: true を指定した Stream Load で更新をまとめるか、Group Commit を使用してください。
  • 主キーの変更。キーを書き換える方法はありません。__DORIS_DELETE_SIGN__ で古い行を論理削除し、新しい行を挿入してください。できれば同じデータロードで行います。
  • 数十億行もの一致する行を対象とする述語 DELETE。削除のたびに、compaction が処理しなければならない述語または bitmap が記録されます。パーティション置換や INSERT OVERWRITE のほうが高速です。
  • Aggregate モデルで、キー以外のカラムを条件にする DELETE。述語で絞り込めるのはキーカラムだけです。エンジンは集約前に値カラムの条件を評価できません。

関連資料​