跳至主要内容

更新数据

ClickHouse 和 OLTP 数据库更新数据的区别

在处理更新方面,ClickHouse 和 OLTP 数据库由于其底层设计理念和目标使用场景的不同而存在显著差异。例如,PostgreSQL 是一种面向行的、符合 ACID 的关系型数据库,支持强大的事务性更新和删除操作,通过多版本并发控制 (MVCC) 等机制确保数据一致性和完整性。这允许即使在高并发环境中也能安全可靠地进行修改。

相反,ClickHouse 是一种面向列的数据库,针对读密集型分析和高吞吐量追加式操作进行了优化。虽然它本身支持就地更新和删除,但必须谨慎使用以避免高 I/O。或者,可以重新构建表以将删除和更新转换为追加操作,这些操作在异步和/或读取时进行处理,从而反映出对高吞吐量数据摄取和高效查询性能相对于实时数据操作的关注。

在 ClickHouse 中更新数据的方法

在 ClickHouse 中更新数据有多种方法,每种方法都有其自身的优点和性能特点。应根据您的数据模型以及您要更新的数据量选择合适的方法。

对于这两种操作,如果提交的变动数量持续超过一段时间内在后台处理的变动数量,则必须应用的未实现变动队列将不断增长。这将导致最终的 SELECT 查询性能下降。

总之,更新操作应谨慎执行,应使用 system.mutations 表密切跟踪变动队列。不要像在 OLTP 数据库中那样频繁地执行更新。如果您需要频繁更新,请参阅 ReplacingMergeTree.

方法语法何时使用
更新变动ALTER TABLE [table] UPDATE当数据必须立即更新到磁盘时使用(例如,为了合规性)。会对 SELECT 性能产生负面影响。
轻量级更新ALTER TABLE [table] UPDATE使用 SET apply_mutations_on_fly = 1; 启用。当更新少量数据时使用。在所有后续 SELECT 查询中,行会立即返回更新后的数据,但最初只在磁盘上被标记为已更新。
ReplacingMergeTreeENGINE = ReplacingMergeTree当更新大量数据时使用。此表引擎针对数据合并时的重复数据消除进行了优化。

以下是 ClickHouse 中更新数据不同方式的总结

更新变动

更新变动 - 可以通过 ALTER TABLE … UPDATE 命令发出,例如:

ALTER TABLE posts_temp
(UPDATE AnswerCount = AnswerCount + 1 WHERE AnswerCount = 0)

这些操作非常占用 I/O,会重写所有与 WHERE 表达式匹配的部分。此过程没有原子性 - 部分在准备好后立即被替换为已变动的部分,并且在变动期间开始执行的 SELECT 查询将看到来自已变动部分的数据以及来自尚未变动部分的数据。用户可以通过 systems.mutations 表跟踪进度状态。这些是 I/O 密集型操作,应谨慎使用,因为它们会影响集群的 SELECT 性能。

阅读有关 更新变动 的更多信息。

轻量级更新(仅在 ClickHouse Cloud 中可用)

轻量级更新提供了一种机制来更新行,使它们立即更新,并且后续的 SELECT 查询将自动返回更改后的值(这会产生开销,并且会降低查询速度)。这有效地解决了普通变动的原子性限制。我们在下面展示一个示例

SET apply_mutations_on_fly = 1;

SELECT ViewCount
FROM posts
WHERE Id = 404346

┌─ViewCount─┐
26762
└───────────┘

1 row in set. Elapsed: 0.115 sec. Processed 59.55 million rows, 238.25 MB (517.83 million rows/s., 2.07 GB/s.)
Peak memory usage: 113.65 MiB.

-increment count
ALTER TABLE posts
(UPDATE ViewCount = ViewCount + 1 WHERE Id = 404346)

SELECT ViewCount
FROM posts
WHERE Id = 404346

┌─ViewCount─┐
26763
└───────────┘

1 row in set. Elapsed: 0.149 sec. Processed 59.55 million rows, 259.91 MB (399.99 million rows/s., 1.75 GB/s.)

请注意,对于轻量级更新,仍使用变动来更新数据;它只是不会立即实现,而是在 SELECT 查询期间应用。它仍然会在后台作为异步进程应用,并且会产生与变动相同的巨大开销,因此它是一个 I/O 密集型操作,应谨慎使用。此操作可以使用表达式的范围也有限(有关 详细信息,请参见此处)。

阅读有关 轻量级更新 的更多信息。

更多资源