ClickHouse 21.7.3.14-2(十一) 数据一致性

查询 CK 手册发现,即便对数据一致性支持最好的 Mergetree,也只是保证最终一致性.我们在使用 ReplacingMergeTree、SummingMergeTree 这类表引擎的时候,会出现短暂数据不一致的情况。在某些对一致性非常敏感的场景,通常有以下几种解决方案。

手动 OPTIMIZE(不建议)

在写入数据后,立刻执行 OPTIMIZE 强制触发新写入分区的合并动作。

OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]

通过 Group by 去重

可以根据自己实际重复的字段进行去重,然后对每个重复的组里选自己想要的数据。

select 
 user_id,
 argMax(score, create_time) AS score,
 argMax(deleted, create_time) AS deleted,
 max(create_time) AS ctime
from a
group by user_id
# 分组完成后查询未被删除的数据
HAVING deleted = 0;

argMax(field1,field2) 按照 field2 的最大值取 field1 的值。

这种固定的查询语句我们可以提前封装为一个视图,以后只查视图就好了

CREATE VIEW view_a AS
SELECT
 user_id ,
 argMax(score, create_time) AS score,
 argMax(deleted, create_time) AS deleted,
 max(create_time) AS ctime
FROM a
GROUP BY user_id
HAVING deleted = 0;

查询视图

SELECT * FROM view_test_a WHERE user_id = 0;

通过 FINAL 查询

在查询语句后增加 FINAL 修饰符,这样在查询的过程中将会执行 Merge 的特殊逻辑(例如数据去重,预聚合等)。

但是这种方法在早期版本基本没有人使用,因为在增加 FINAL 之后,我们的查询将会变成一个单线程的执行过程,查询速度非常慢。在 v20.5.2.7-stable 版本中,FINAL 查询支持多线程执行,并且可以通过 max_final_threads 参数控制单个查询的线程数。但是目前读取 part 部分的动作依然是串行的。

FINAL 查询最终的性能和很多因素相关,列字段的大小、分区的数量等等都会影响到最终的查询时间,所以还要结合实际场景取舍。final 只能在部分表引擎中使用。

语法

# 普通查询
select * from visits_v1 WHERE StartDate = '2014-03-17' limit 100 settings max_threads = 2;

# final 查询
select * from visits_v1 final WHERE StartDate = '2014-03-17' limit 100 settings max_final_threads = 2;

可以通过查看以上语法的执行计划,会发现使用 final 关键字后,在分区的的数据查询时,会是单线程执行,即使设置了线程数为2.

最终使用哪种方式保证数据一致性,可以用第2或第3种对已有的数据进行测试后在决定,在不同的数据量,不同的情况,两者性能存在着差异。

你可能感兴趣的:(ClickHouse 21.7.3.14-2(十一) 数据一致性)