> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-trino-dialect.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> 轻量级更新通过使用补丁分区片段，简化了数据库中数据的更新过程。

# 轻量级 UPDATE 语句

export const BetaBadge = ({link, galaxyTrack, galaxyEvent}) => {
  if (link) {
    return <a href={link} target="_blank" rel="noopener noreferrer" className="betaBadge" onClick={galaxyTrack && galaxyEvent ? galaxyOnClick(galaxyEvent) : undefined}>
                <span>Beta</span>
            </a>;
  }
  return <a href="https://clickhouse.com/docs/reference/settings/beta-and-experimental-features#beta-features" className="betaBadge">
            <span>Beta 版功能</span>
        </a>;
};

<BetaBadge />

<Note>
  轻量级更新目前处于 Beta 阶段。
  如果您遇到问题，请在 [ClickHouse 仓库](https://github.com/clickhouse/clickhouse/issues) 中提交 issue。
</Note>

轻量级 `UPDATE` 语句会更新表 `[db.]table` 中与表达式 `filter_expr` 匹配的行。
之所以称其为“轻量级更新”，是为了与 [`ALTER TABLE ... UPDATE`](/zh/reference/statements/alter/update) 查询区分开来；后者是一个重量级过程，会重写数据分区片段中的整列。
它仅适用于 [`MergeTree`](/zh/reference/engines/table-engines/mergetree-family/mergetree) 表引擎家族。

```sql theme={null}
UPDATE [db.]table [ON CLUSTER cluster] SET column1 = expr1 [, ...] [IN PARTITION partition_expr] WHERE filter_expr;
```

`filter_expr` 必须是 `UInt8` 类型。此查询会将指定列在 `filter_expr` 取非零值的行中的值，更新为相应表达式的值。
这些值会使用 `CAST` 运算符转换为列类型。不支持更新用于计算主键或分区键的列。

<div id="examples">
  ## 示例
</div>

```sql theme={null}
UPDATE hits SET Title = 'Updated Title' WHERE EventDate = today();

UPDATE wikistat SET hits = hits + 1, time = now() WHERE path = 'ClickHouse';
```

<div id="lightweight-update-does-not-update-data-immediately">
  ## 轻量级更新不会立即更新数据
</div>

轻量级 `UPDATE` 通过 **patch parts** 实现——这是一种特殊的数据分区片段，只包含已更新的列和行。
轻量级 `UPDATE` 会创建补丁分区片段，但不会立即在存储中对原始数据进行物理修改。
更新过程类似于 `INSERT ... SELECT ...` 查询，但 `UPDATE` 查询会等到补丁分区片段创建完成后才返回。

更新后的值将会：

* 通过应用补丁在 `SELECT` 查询中**立即可见**
* 仅会在后续的合并和变更过程中被**物理物化**
* 一旦所有活跃 parts 都已完成补丁物化，便会被**自动清理**

<div id="lightweight-update-requirements">
  ## 轻量级更新要求
</div>

[`MergeTree`](/zh/reference/engines/table-engines/mergetree-family/mergetree)、[`ReplacingMergeTree`](/zh/reference/engines/table-engines/mergetree-family/replacingmergetree)、[`CollapsingMergeTree`](/zh/reference/engines/table-engines/mergetree-family/collapsingmergetree)、[`VersionedCollapsingMergeTree`](/zh/reference/engines/table-engines/mergetree-family/versionedcollapsingmergetree) 引擎及其 [`Replicated`](/zh/reference/engines/table-engines/mergetree-family/replication) 和 [`Shared`](/zh/products/cloud/features/infrastructure/shared-merge-tree) 版本均支持轻量级更新。

要使用轻量级更新，必须通过表设置 [`enable_block_number_column`](/zh/reference/settings/merge-tree-settings/enable-block#enable_block_number_column) 和 [`enable_block_offset_column`](/zh/reference/settings/merge-tree-settings/enable-block#enable_block_offset_column) 启用 `_block_number` 和 `_block_offset` 列的物化。

<div id="lightweight-delete">
  ## 轻量级删除
</div>

[轻量级 `DELETE`](/zh/reference/statements/delete) 查询可以通过轻量级 `UPDATE` 的方式执行，而不是作为 `ALTER UPDATE` 变更执行。轻量级 `DELETE` 的实现由设置 [`lightweight_delete_mode`](/zh/reference/settings/session-settings/lightweight#lightweight_delete_mode) 控制。

<div id="performance-considerations">
  ## 性能注意事项
</div>

**轻量级更新的优势：**

* 更新延迟与 `INSERT ... SELECT ...` 查询的延迟相当
* 仅写入已更新的列和值，而不是数据分区片段中的整列
* 无需等待当前正在运行的合并/变更完成，因此更新延迟可预测
* 轻量级更新支持并行执行

**潜在的性能影响：**

* 会给需要应用补丁的 `SELECT` 查询带来额外开销
* 对于存在待应用补丁的数据分区片段中的列，将不会使用[跳过索引](/zh/reference/engines/table-engines/mergetree-family/mergetree#table_engine-mergetree-data_skipping-indexes)。如果表中存在补丁分区片段，则不会使用[投影](/zh/reference/engines/table-engines/mergetree-family/mergetree#projections)，这也包括那些没有待应用补丁的数据分区片段。
* 过于频繁的小规模更新可能会导致“parts 过多”错误。建议将多次更新合并到单个查询中，例如将待更新的 id 放在 `WHERE` 子句中的同一个 `IN` 子句里
* 轻量级更新适合更新少量行 (最多约占表的 10%) 。如果需要更新更多数据，建议使用 [`ALTER TABLE ... UPDATE`](/zh/reference/statements/alter/update) 变更

<div id="concurrent-operations">
  ## 并发操作
</div>

与重量级变更不同，轻量级更新不会等待当前正在进行的合并/变更完成。
并发轻量级更新的一致性由设置 [`update_sequential_consistency`](/zh/reference/settings/session-settings/update#update_sequential_consistency) 和 [`update_parallel_mode`](/zh/reference/settings/session-settings/update#update_parallel_mode) 控制。

<div id="update-permissions">
  ## 更新权限
</div>

`UPDATE` 需要 `ALTER UPDATE` 权限。要为指定用户授予在特定表上执行 `UPDATE` 语句的权限，请运行：

```sql theme={null}
GRANT ALTER UPDATE ON db.table TO username;
```

<div id="details-of-the-implementation">
  ## 实现细节
</div>

补丁分区片段与常规 parts 相同，但只包含更新后的列、表的排序键列以及以下系统列：

* `_part` - 原始 part 的名称
* `_block_number` - 原始 part 中该行的块编号
* `_block_offset` - 原始 part 中该行的块内偏移
* `_data_version` - 更新后数据的数据版本 (为 `UPDATE` 查询分配的块编号)

系统列有助于定位原始 part 中需要更新的行。
系统列与原始 part 中的[虚拟列](/zh/reference/engines/table-engines/mergetree-family/mergetree#virtual-columns)相关；如果需要应用补丁分区片段，这些列会在读取时被添加。
补丁分区片段按表的排序键排序，并在其后追加 `_block_number` 和 `_block_offset` 列。
每个更新行的存储开销取决于排序键列值的大小。

补丁分区片段所属的分区与原始 part 不同。
补丁分区片段的分区 id 为 `patch-<hash of the patch part structure>-<original_partition_id>`。
因此，包含不同列的补丁分区片段会存储在不同的分区中。
例如，三个更新 `SET x = 1 WHERE <cond>`、`SET y = 1 WHERE <cond>` 和 `SET x = 1, y = 1 WHERE <cond>` 会在三个不同的分区中创建三个补丁分区片段。

补丁分区片段之间可以相互合并，以减少在 `SELECT` 查询中需要应用的补丁数量并降低开销。补丁分区片段的合并使用 [ReplacingMergeTree](/zh/reference/engines/table-engines/mergetree-family/replacingmergetree) 的合并算法，并以 `_data_version` 作为版本列。
因此，补丁分区片段始终会为 part 中每个更新过的行保存最新版本。

补丁分区片段通过表的排序键与数据分区片段合并来应用：如果数据分区片段和补丁分区片段中排序键列以及 `_block_number` 和 `_block_offset` 列的值相等，则会更新该行。
即使查询未选择数据分区片段的排序键列，应用补丁分区片段时也需要读取这些列。
应用补丁分区片段的内存使用量受排序键值相同的最大行范围限制。

<div id="patch-parts-format-in-mixed-version-clusters">
  ### 混合版本集群中的补丁分区片段格式
</div>

新写入的补丁分区片段格式由表级设置 [`patch_parts_version`](/zh/reference/settings/merge-tree-settings) 控制。
26.8 之前的 ClickHouse 版本仅支持旧版 `v1` 格式，无法读取上述当前 `v2` 格式的补丁分区片段。
从此类版本进行滚动升级时，在所有副本完成升级之前，请继续写入 `v1` 格式：对于使用轻量级更新的表，设置 `patch_parts_version = 'v1'`；或者将 [`compatibility`](/zh/reference/settings/session-settings/compatibility#compatibility) 设置为正在升级的源版本。
升级完成后，移除该覆盖设置，即可开始按 `v2` 格式写入补丁分区片段。
无论设置值为何，两种格式的补丁分区片段均可读取和应用。

<div id="related-content">
  ## 相关内容
</div>

* [`ALTER UPDATE`](/zh/reference/statements/alter/update) - 高开销的 `UPDATE` 操作
* [轻量级 `DELETE`](/zh/reference/statements/delete) - 轻量级 `DELETE` 操作
* [`APPLY PATCHES`](/zh/reference/statements/alter/apply-patches) - 强制将补丁物化到数据分区片段中 (变更操作)
