轻量级删除
轻量级 DELETE 语句从表 [db.]table 中删除匹配表达式 expr 的行。它仅适用于 *MergeTree 表引擎系列。
将其称为“轻量级 DELETE”是为了与 ALTER TABLE ... DELETE 命令形成对比,后者是一个重量级过程。
示例
轻量级 DELETE 不会立即删除数据
轻量级 DELETE 实现为一种 mutation,它将行标记为已删除,但不会立即物理删除它们。
默认情况下,DELETE 语句会等到标记行已删除完成之后才返回。如果数据量很大,这可能需要很长时间。或者,您可以使用设置 lightweight_deletes_sync 以异步方式在后台运行它。如果禁用,DELETE 语句将立即返回,但数据在后台 mutation 完成之前仍然可能对查询可见。
mutation 不会物理删除已标记为已删除的行,这仅会在下一次合并期间发生。因此,有可能在未指定的期间内,数据实际上并未从存储中删除,而仅被标记为已删除。
如果您需要保证数据在可预测的时间内从存储中删除,请考虑使用表设置 min_age_to_force_merge_seconds。或者,您可以使用 ALTER TABLE ... DELETE 命令。请注意,使用 ALTER TABLE ... DELETE 删除数据可能会消耗大量资源,因为它会重新创建所有受影响的部分。
删除大量数据
大量删除可能会对 ClickHouse 性能产生负面影响。如果您尝试从表中删除所有行,请考虑使用 TRUNCATE TABLE 命令。
如果您预计会频繁删除,请考虑使用 自定义分区键。然后,您可以使用 ALTER TABLE ... DROP PARTITION 命令快速删除与该分区关联的所有行。
轻量级 DELETE 的限制
带有 projections 的轻量级 DELETE
默认情况下,DELETE 不适用于带有 projections 的表。这是因为 projection 中的行可能会受到 DELETE 操作的影响。但是,有一个 MergeTree 设置 lightweight_mutation_projection_mode 可以更改该行为。
使用轻量级 DELETE 时的性能注意事项
使用轻量级 DELETE 语句删除大量数据可能会对 SELECT 查询性能产生负面影响。
以下因素也可能对轻量级 DELETE 性能产生负面影响
DELETE查询中存在繁重的WHERE条件。- 如果 mutation 队列中填充了许多其他 mutation,这可能会导致性能问题,因为表上的所有 mutation 都是按顺序执行的。
- 受影响的表具有大量数据部分。
- 拥有大量数据在 compact 部分中。在 Compact 部分中,所有列都存储在一个文件中。
删除权限
DELETE 需要 ALTER DELETE 权限。要在给定用户针对特定表启用 DELETE 语句,请运行以下命令
ClickHouse 中轻量级 DELETE 内部工作原理
-
对受影响的行应用“mask”
当执行
DELETE FROM table ...查询时,ClickHouse 会保存一个 mask,其中每行都被标记为“存在”或“已删除”。这些“已删除”的行将在后续查询中被省略。但是,行实际上只有在后续合并时才会被删除。写入此 mask 比ALTER TABLE ... DELETE查询所做的工作轻量得多。mask 实现为隐藏的
_row_exists系统列,它为所有可见行存储True,为已删除的行存储False。如果部分中的某些行已被删除,则此列仅存在于该部分中。当部分中的所有值都等于True时,此列不存在。 -
SELECT查询被转换为包含 mask当在查询中使用 masked 列时,
SELECT ... FROM table WHERE condition查询会在内部通过_row_exists上的谓词进行扩展,并转换为在执行时,读取列
_row_exists以确定哪些行不应返回。如果有很多已删除的行,ClickHouse 可以确定可以完全跳过哪些 granules 在读取其余列时。 -
DELETE查询被转换为ALTER TABLE ... UPDATE查询DELETE FROM table WHERE condition被转换为ALTER TABLE table UPDATE _row_exists = 0 WHERE conditionmutation。在内部,此 mutation 分两个步骤执行
-
为每个部分执行
SELECT count() FROM table WHERE condition命令,以确定该部分是否受到影响。 -
基于上述命令,然后对受影响的部分进行 mutation,并为未受影响的部分创建硬链接。对于宽部分,为每行更新
_row_exists列,并硬链接所有其他列的文件。对于 compact 部分,会重新写入所有列,因为它们都存储在同一个文件中。
从上述步骤可以看出,使用 masking 技术进行轻量级
DELETE比传统的ALTER TABLE ... DELETE提高了性能,因为它不会重新写入受影响部分的所有列文件。 -