Skip to main content
論理更新は現在ベータです。 問題が発生した場合は、ClickHouseリポジトリ に issue を登録してください。
論理更新 UPDATE ステートメントは、式 filter_expr に一致するテーブル [db.]table の行を更新します。 これは、データパーツ内のカラム全体を書き換える重量級の処理である ALTER TABLE ... UPDATE クエリと対比して、“論理更新” と呼ばれています。 この機能は、MergeTree テーブルエンジンファミリーでのみ利用できます。
filter_exprUInt8 型である必要があります。このクエリは、filter_expr が非ゼロ値となる行について、指定したカラムの値を、それぞれ対応する式の値に更新します。 値は CAST 演算子を使用してカラムの型にキャストされます。プライマリキーまたはパーティションキーの計算に使用されるカラムの更新はサポートされていません。

論理更新ではデータは即座に更新されません

論理更新 UPDATE は、パッチパート (更新されたカラムと行のみを含む特殊なデータパート) を使用して実装されています。 論理更新 UPDATE ではパッチパートが作成されますが、ストレージ内の元データが直ちに物理的に変更されるわけではありません。 更新処理は INSERT ... SELECT ... クエリに似ていますが、UPDATE クエリはパッチパートの作成が完了するまで待機してから結果を返します。 更新後の値は次のとおりです。
  • パッチの適用により、SELECT クエリから即座に参照可能
  • 物理的に実体化されるのは、後続のマージやミューテーションの実行時のみ
  • アクティブなすべてのパーツでパッチが実体化されると、自動的にクリーンアップされる

論理更新の要件

論理更新は、MergeTreeReplacingMergeTreeCollapsingMergeTreeVersionedCollapsingMergeTree エンジンと、それらの Replicated および Shared バージョンでサポートされています。 論理更新を使用するには、テーブル設定 enable_block_number_columnenable_block_offset_column を使用して、_block_number および _block_offset カラムの実体化を有効にする必要があります。

論理削除

論理削除 DELETE クエリは、ALTER UPDATE ミューテーションではなく、論理更新 UPDATE として実行できます。論理削除 DELETE の実装は、lightweight_delete_mode 設定によって制御されます。

パフォーマンスに関する考慮事項

論理更新の利点:
  • 更新のレイテンシは、INSERT ... SELECT ... クエリのレイテンシと同程度です
  • 書き込まれるのは更新されたカラムと値のみであり、データパーツ内のカラム全体は書き換えられません
  • 現在実行中のマージやミューテーションの完了を待つ必要がないため、更新のレイテンシは予測しやすくなります
  • 論理更新は並列に実行できます
想定されるパフォーマンスへの影響:
  • パッチを適用する必要がある SELECT クエリにはオーバーヘッドが発生します
  • パッチを適用する必要があるデータパーツ内のカラムでは、スキッピング索引 は使用されません。プロジェクション は、パッチを適用する必要がないデータパーツを含め、テーブルにパッチパートが存在する場合は使用されません。
  • 頻繁すぎる小規模な更新は、“パーツが多すぎる” エラーを引き起こす可能性があります。複数の更新を 1 つのクエリにまとめることを推奨します。たとえば、更新対象の id を 1 つの IN 句にまとめて WHERE 句で指定します
  • 論理更新は、少量の行 (テーブルの約 10% まで) を更新するように設計されています。より多くの行を更新する必要がある場合は、ALTER TABLE ... UPDATE ミューテーションを使用することを推奨します

同時実行操作

論理更新は、重い ミューテーション とは異なり、現在実行中の マージ や ミューテーション の完了を待ちません。 同時実行される論理更新の整合性は、設定 update_sequential_consistencyupdate_parallel_mode によって制御されます。

UPDATE の権限

UPDATE には ALTER UPDATE 権限が必要です。特定のテーブルで特定のユーザーに UPDATE ステートメントを許可するには、次を実行します。

実装の詳細

パッチパートは通常のパーツと同じですが、更新されたカラム、テーブルのソートキーを構成するカラム、および以下のシステムカラムのみを含みます。
  • _part - 元のパーツ名
  • _block_number - 元のパーツ内におけるその行のブロック番号
  • _block_offset - 元のパーツ内におけるその行のブロックオフセット
  • _data_version - 更新データのデータバージョン (UPDATE クエリに割り当てられたブロック番号)
システムカラムは、更新対象となる元のパーツ内の行を特定するのに役立ちます。 これらは元のパーツ内の 仮想カラム に対応しており、パッチパートを適用する必要がある場合は、読み取り時に追加されます。 パッチパートは、テーブルのソートキーに _block_number および _block_offset カラムを追加した順序でソートされます。 更新された1行あたりのストレージオーバーヘッドは、ソートキーカラムの値のサイズに依存します。 パッチパートは、元のパーツとは異なるパーティションに属します。 パッチパートのパーティションIDは patch-<hash of the patch part structure>-<original_partition_id> です。 そのため、含まれるカラムが異なるパッチパートは別々のパーティションに格納されます。 たとえば、3つの更新 SET x = 1 WHERE <cond>, SET y = 1 WHERE <cond> および SET x = 1, y = 1 WHERE <cond> によって、3つの異なるパーティションに3つのパッチパートが作成されます。 パッチパート同士をマージすることで、SELECT クエリで適用されるパッチの数を減らし、オーバーヘッドを削減できます。パッチパートのマージでは、_data_version をバージョンカラムとして replacing マージアルゴリズムを使用します。 そのため、パッチパートには常に、そのパーツ内で更新された各行の最新バージョンが保持されます。 パッチパートは、テーブルのソートキーでデータパートとマージすることで適用されます。データパートとパッチパートでソートキーカラム、および _block_number_block_offset カラムの値が等しい場合、その行は更新されます。 パッチパートの適用では、クエリで選択されていない場合でも、データパートのソートキーカラムを読み取る必要があります。 パッチパートの適用におけるメモリ使用量は、ソートキーの値が等しい行の最大範囲によって上限が定まります。

混在バージョンのクラスターにおけるパッチパートのフォーマット

新たに書き込まれるパッチパートのフォーマットは、テーブルレベルの設定 patch_parts_version によって制御されます。 ClickHouse 26.8 より前のバージョンは従来の v1 フォーマットのみをサポートしており、上記で説明した現行の v2 フォーマットのパッチパートは読み取れません。 このようなバージョンからローリングアップグレードを行う場合は、すべてのレプリカのアップグレードが完了するまで v1 フォーマットで書き込みを続けてください。論理更新を使用するテーブルでは patch_parts_version = 'v1' を設定するか、アップグレード元のバージョンに compatibility 設定を指定します。 アップグレードの完了後は、オーバーライドを削除して v2 フォーマットのパッチパートの書き込みを開始します。 いずれのフォーマットのパッチパートも、設定値にかかわらず読み取りおよび適用できます。
最終更新日 2026年8月18日