You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,查询性能正常。因此我有两个问题:

  1. 这是为何?性能骤降的原因是什么?
  2. 我能否确认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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 20:22:43