clickhouse问题处理
2024-07-10 10:03:18 # clickhouse # 问题处理

clickhouse列中出现大量重复值,如何处理

当clickhouse列出现大量重复数据的时候,我们增加clickhouse这个表的索引粒度,可以在

1
SHOW CREATE TABLE table_name

中看到表结构中有索引粒度,加大这个索引粒度,就可以让稀疏索引的间隔变大,加快读取速度,但是官方不建议更改这个字段

Clickhouse的Merge选择问题

clickhouse的MergeTree分为ReplacingMergeTree和SummingMergeTree,但是这两种都有各种的问题。

使用SummingMergeTree,虽然会预聚合,但是无法保证幂等性,假如是flink写入的时候挂了,就会有重复数据出现。可以使用ReplacingMergeTree,但是这个如果不是同一批次的或者没有进行合并分片这时候的数据也不是最终一致的。我们在生产环境上最好少用手动合并,这个后面会说,怎么解决这个问题

clickhouse实现高性能update和delete的操作

我们创建表的时候有两种方式:

更新操作:

  1. 加上一个字段version,意思为版本号,插入数据的时候版本号+1,查询数据的时候取版本号最大的数据
  2. 将create_time作为标识,直接插入数据,不做更新,查询的时候取create_time最大的数据

删除操作:

  1. 用一个标记字段sign。0表示没有删除,1表示已经删除,

    删除数据的时候添加一条一样的数据,把这条数据的sign字段记为1,然后version+1

    每次查询的时候加上where sign =0 and version最大

需要注意的是这两种方式都要定时把过期数据清理掉,不然会占用大量的空间

写入过快报错

当一次写入过多分区或者数据写入过快的时候,就会报错,因为Merge跟不上

1
2
3
1. Code: 252, e.displayText() = DB::Exception: Too many parts(304). Merges are processing significantly slower than inserts
2. Code: 241, e.displayText() = DB::Exception: Memory limit (for query) exceeded:would use 9.37 GiB (attempt to allocate chunk of 301989888 bytes), maximum: 9.31 GiB

解决办法:

in_memory_parts_enable_wal 默认为 true。使用WAL预写日志来实现

为什么Final比普通查询慢

不使用final查询的情况:
alt text

这个执行计划显示查询将由2个线程并行读取数据,读取操作是并行进行的,因此能够加快读取速度。

使用final查询的情况:
alt text

MergeTree 0 → 1:

从MergeTree表读取数据,但这一部分是串行执行的。

这个执行计划显示在执行 FINAL 查询时,数据读取阶段仍然是串行的,但是在后续的数据处理阶段(如表达式转换和数据合并排序)是并行的。

这就是为什么 FINAL 查询比普通查询慢,因为它涉及更多的数据处理步骤,而且读取数据时没有并行化。