Skip to main content

Lightweight Delete

轻量级的DELETE语句会从表[db.]table中删除与表达式expr匹配的行。它仅适用于*MergeTree表引擎系列。

``` sql
DELETE FROM [db.]table [ON CLUSTER cluster] WHERE expr;
```

它被称为“轻量级DELETE”以与ALTER table DELETE命令进行对比,后者是一个繁重的过程。

示例

-- 删除`hits`表中所有`Title`列包含文本`hello`的行
DELETE FROM hits WHERE Title LIKE '%hello%';

轻量级DELETE不会立即从存储中删除数据

使用轻量级DELETE,删除的行会立即被标记为已删除,并且会自动在所有后续查询中被过滤掉。然而,数据的清理是在下一次合并时进行的。因此,可能在未指定的时间内,数据实际上并没有从存储中删除,而只是被标记为已删除。

如果您需要保证数据在可预测的时间内从存储中删除,请考虑使用ALTER table DELETE命令。请注意,使用ALTER table DELETE命令可能会消耗大量资源,因为它会重新创建所有受影响的部分。

删除大量数据

大量的删除可能会对ClickHouse的性能产生负面影响。如果您尝试从表中删除所有行,请考虑使用TRUNCATE TABLE命令。

如果您预计会频繁删除数据,请考虑使用自定义分区键。然后,您可以使用ALTER TABLE...DROP PARTITION命令快速删除与该分区相关的所有行。

轻量级DELETE的限制

轻量级DELETE不适用于投影

目前,DELETE不适用于具有投影的表。这是因为投影中的行可能会受到DELETE操作的影响,并且可能需要重建投影,从而对DELETE的性能产生负面影响。

使用轻量级DELETE时的性能考虑

使用轻量级DELETE语句删除大量数据可能会对SELECT查询性能产生负面影响。

以下情况也可能对轻量级DELETE的性能产生负面影响:

  • DELETE查询中的重型WHERE条件。
  • 如果变异队列中填充了许多其他变异,这可能会导致性能问题,因为表上的所有变异都是顺序执行的。
  • 受影响的表具有非常多的数据部分。
  • 在紧凑部分中有大量数据。在紧凑部分中,所有列都存储在一个文件中。

删除权限

DELETE需要ALTER DELETE权限。要为给定用户的特定表启用DELETE语句,请运行以下命令:

GRANT ALTER DELETE ON db.table to username;

在ClickHouse中使用轻量级DELETE的内部工作原理

  1. 对受影响的行应用“掩码”

当执行DELETE FROM table ...查询时,ClickHouse会保存一个掩码,其中每一行都被标记为“现有”或“已删除”。那些“已删除”的行在后续查询中会被省略。然而,实际上只有在后续合并时才会删除行。写入这个掩码比使用ALTER table DELETE查询要轻量得多。

掩码是作为一个隐藏的_row_exists系统列来实现的,它存储了对于所有可见行为True,对于已删除行为False。这个列只在部分行中存在,如果部分行中的一些行被删除了。当一个部分的所有值都等于True时,这个列是不存在的。

  1. SELECT查询转换为包含掩码的查询

当查询中使用了掩码列时,SELECT ... FROM table WHERE condition查询在内部被扩展为:

SELECT ... FROM table PREWHERE _row_exists WHERE condition

在执行时,列_row_exists被读取以确定哪些行不应该被返回。如果有很多已删除的行,ClickHouse可以确定在读取其余列时可以完全跳过哪些粒度。

  1. DELETE查询被转换为ALTER table UPDATE查询

DELETE FROM table WHERE condition被翻译为ALTER table UPDATE _row_exists = 0 WHERE condition变异。

在内部,这个变异是通过两个步骤来执行的:

  1. 对于每个单独的部分,执行SELECT count() FROM table WHERE condition命令来确定部分是否受到影响。
  2. 基于上述命令,受影响的部分然后被变异,对于未受影响的部分创建硬链接。在宽部分的情况下,为每一行更新_row_exists列,并且所有其他列的文件都被硬链接。对于紧凑部分,所有列都会被重新写入,因为它们都存储在一个文件中。

从上面的步骤中,我们可以看到,使用掩码技术的轻量级删除比传统的ALTER table DELETE命令提高了性能,因为ALTER table DELETE读取并重新写入了所有受影响部分的列文件。

相关内容