ClickHouse含FINAL的查询性能骤降原因及稳定性咨询
问题背景与疑问
我对campaign_impression表执行了OPTIMIZE TABLE ... FINAL;操作。随后执行带FINAL的SELECT查询,查询条件中的date_time范围仅包含OPTIMIZE操作前生成的数据,处理了1.36亿行数据,耗时0.847秒。
重复该查询时,将date_time条件向后调整1分钟(查询范围包含未被OPTIMIZE的数据),仅多处理了7万行数据(增加0.05%),但耗时却达到3.605秒,性能差异极大。
若SELECT语句中不带FINAL,查询性能正常。因此我有两个问题:
- 这是为何?性能骤降的原因是什么?
- 我能否确认OPTIMIZE操作前的所有数据始终能保持如此快的查询速度?
表结构
CREATE TABLE campaign_impression ON CLUSTER 'statistics' ( date_time DateTime('UTC'), campaign_id Int64, impression_environment Enum('WEB' = 1, 'IN_APP' = 2), action_type Enum('IMPRESSION' = 1, 'CLICK' = 2), event_log_id Int64, hit_log_id UInt64, banner_id UInt64, ad_group_id UInt64 ) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/statistics/{shard}/default/campaign_impression', '{replica}') PARTITION BY toYYYYMM(date_time) ORDER BY (campaign_id, date_time, event_log_id) PRIMARY KEY (campaign_id, date_time);
执行的查询语句
SELECT toStartOfInterval(toTimeZone(date_time, 'UTC'), INTERVAL 1 DAY) AS interval_start, action_type, impression_environment, count(*) AS count FROM campaign_impression FINAL WHERE date_time >= '2023-01-13' AND date_time < '2024-01-16 14:35:00' AND campaign_id = 491 GROUP BY action_type, interval_start, impression_environment ORDER BY interval_start DESC SETTINGS do_not_merge_across_partitions_select_final = 1 FORMAT Null;
ClickHouse版本:23.12
问题解答
1. 性能骤降的原因
你的表基于ReplacingMergeTree引擎,FINAL关键字的作用是在查询时实时执行合并去重,确保返回数据的最终状态。
- 当查询仅覆盖已OPTIMIZE的分区时,这些分区已经完成了合并去重,数据是按
ORDER BY规则排序的紧凑结构。此时FINAL无需额外计算,直接读取合并后的结果即可,所以速度极快。 - 当查询范围包含未OPTIMIZE的新数据时,这些数据处于未合并的零散小parts中。
FINAL需要对这些parts执行实时合并去重:针对同一ORDER BY键下的重复数据做比对、保留最新版本,这个过程会消耗额外的CPU和内存资源。哪怕新增数据量极小,也会触发该分区内的全量合并逻辑(你设置的do_not_merge_across_partitions_select_final=1只是避免跨分区合并,单个分区内的未合并parts仍需处理)。 - 另外,未合并的小parts属于零散小文件,读取时的IO效率远低于合并后的大文件,进一步加剧了查询耗时。
2. 能否确保OPTIMIZE前的数据始终快速查询
可以,但需要满足以下条件:
- 这些数据所在的分区不再写入新数据,且已通过
OPTIMIZE TABLE ... FINAL完成合并。一旦分区标记为合并完成,ClickHouse会保留合并后的紧凑part,不会自动拆分。 - 不对这些分区执行触发重新合并的操作(比如手动再次执行
OPTIMIZE、修改表结构导致分区重写等)。 - 查询的
WHERE条件能命中PRIMARY KEY或ORDER BY的前缀(你的查询中campaign_id和date_time都是主键前缀,符合要求),确保ClickHouse能快速定位目标数据范围,避免全表扫描。
满足以上条件后,OPTIMIZE后的分区数据在使用FINAL查询时,会一直保持高效的读取速度,因为无需再执行实时合并逻辑。
内容的提问来源于stack exchange,提问作者BOOMeranGG
相关产品推荐
相关产品推荐

