ClickHouse 性能测试完整实操指南:3步跑通 TPC-H,横评 PostgreSQL/MySQL 实测数据说话
ClickHouse 性能测试完整实操指南:3步跑通 TPC-H,横评 PostgreSQL/MySQL 实测数据说话
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
同一张约 10 亿行的表,全表聚合查询:MySQL 量级在 30s 上下,PostgreSQL 约 20~30s,ClickHouse 实测能压到 1s 以内。这就是这篇文章要带你做的事——不背概念,直接用 clickhouse-benchmark 和 tests/benchmarks/ 里的 TPC-H、TPC-DS 套件把 ClickHouse 性能测试跑起来,再和 PostgreSQL、MySQL 做一轮变量可控的基准测试对比,最后给出 4 个当天见效的调优动作。全文约 3000 字,跟着做即可复现。
你的查询到底慢在哪:query_log 和 explain 是前两道
拿到一个慢查询,先别动配置,先回答一个问题:时间是花在算、还是花在等 I/O?
第一步查system.query_log,一条 SQL 定位慢查询,看elapsed_us、result_rows、read_rows三个字段:读了几亿行只吐出一行结果,多半是谓词没下推或者排序键白建了;read_rows很小但依然慢,去查网络和副本。
SELECT query_id, elapsed_us, read_rows, read_bytes, query FROM system.query_log WHERE event_date = today() AND type = 'QueryFinish' ORDER BY elapsed_us DESC LIMIT 10;第二步看执行计划和逐节点耗时:EXPLAIN PIPELINE看线程调度,EXPLAIN PLAN看谓词下推,SYSTEM PROFILE EVENTS或system.processors_profile_events看每个算子实际跑的时间。定位到瓶颈后,才轮到基准测试出场——用 clickhouse-benchmark 用法 把"这个查询在新旧配置下各跑 100 次"变成可复现的数字,而不是靠感觉判断"好像快了"。
3 步跑通 TPC-H 22 条查询,指标怎么看才不踩坑
tests/benchmarks/ 下每个套件都是自包含的,以tpc-h/为例,目录里只有三样东西:init.sql(建表语句)、settings.json(跑查询时强制的会话参数,比如join_use_nulls = 1,保证各数据库在同一套语义下比)、queries/(22 条标准查询,逐条编号命名)。tpc-ds/结构相同,只是查询集换成 99 条更复杂的数据仓库场景。
三步跑完:
clickhouse-client --query " DROP DATABASE IF EXISTS tpc_h; CREATE DATABASE tpc_h; ATTACH DATABASE tpc_h" clickhouse-client --database tpc_h --multiquery < tests/benchmarks/tpc-h/init.sql clickhouse-benchmark --query "SELECT ... " --iterations 100实际上 init.sql 之外还需要灌数据(官方用 dbgen 或 ClickHouse 的 TPC-H 数据生成器,仓库内 CI 脚本有现成流程),灌完 22 条查询逐条执行即可。两个已知坑直接说:Q6 原始写法在 ClickHouse 上有 Decimal 精度问题,tpc-h/README.md 里给了带类型转换的替代写法;Q11 的 FRACTION 参数要按 scale factor 调整。
跑完别只看平均延迟,这是新手最常犯的错。100 次执行里平均 0.8s、P99 却是 3s,说明有冷缓存、后台 merge 或内存换页在捣乱,这个"平均 0.8s"写进报告就是事故。正确的读法:
- P50代表常态体验,用来做横向对比的主指标
- P99 / P99.9代表最坏路径,用来判断稳定性;P99 超过 P50 两倍以上,先查是不是混进了首轮冷查询
- 对比前先跑 5~10 轮预热丢弃,让页缓存和标记数据热起来
clickhouse-benchmark的--time、--iterations参数就是干这个的,它自带 QPS、RPS 统计,把每条查询的分布跑出来,比单条手动计时可靠得多。
横向对比方法论:先控制变量,再看 PostgreSQL / MySQL 各输在哪
拿三台机器随便跑一轮,出来的数字一文不值。ClickHouse vs PostgreSQL 性能对比要可信,四个变量必须锁死:
- 硬件:同机型、同核数(建议 16 核起步)、SSD、内存至少 64GB,三库装在同规格环境;至少保证对比时只改数据库,不换机器
- 数据量:用同一份生成脚本灌数,比如 10 亿行事实表 + 维度表,记录好导入后的行数核对一致
- 并发数:从单连接跑起,再逐步加到 16、32 并发,画出并发-延迟曲线,而不是只报单线程一个点
- 预热轮次:每轮正式测量前跑 5 次丢弃,消除冷缓存差异
测试数据怎么准备是这套方法论里最容易偷懒的环节。原则是"贴近生产分布":时间戳按业务节奏分布而不是全落在今天,字符串列保留真实的基数特征,ID 用乱序还是有序要说明白。拿不到生产数据时,优先用公开的真实数据集灌进去测——下面这种现成样本库就比自己rand()出来的数据更有代表性:
在 10 亿行、16 核、NVMe 的环境量级下,三类查询的胜负手大致是:
| 查询场景 | PostgreSQL | ClickHouse | 优势倍数 |
|---|---|---|---|
| 全表聚合(GROUP BY + sum/avg) | 20~30s | 0.5~2s | 10x~50x |
| 中等 JOIN(1000 万行两表) | 8~15s | 2~5s | 约 3x |
| 主键点查(单行返回) | 毫秒级 | 10~50ms | PostgreSQL 胜 |
结论别照抄数字,抄结构:聚合查询是 ClickHouse 的主场——列式存储让扫描只读需要的列,向量化执行让每列一次处理一批,这是 ClickHouse 列式存储 优势 的底层来源;JOIN 场景 ClickHouse 赢但赢法不同,它更鼓励你宽表化/预聚合把 JOIN 消掉,而不是靠哈希 JOIN 硬扛大表关联;点查是行存的主场,ClickHouse 的单点查询要付列式读取的固定开销,真要低延迟点查,要么用 ReplacingMergeTree 小表 + 索引,要么承认这种负载不适合放进来。
从慢到快:4 个调优动作按收益从大到小排
① 排序键(PRIMARY KEY)设计——收益最大,因为它决定了扫描量。MergeTree 的 ORDER BY 是主键索引也是分区内物理排序,把查询里最常用的过滤前缀放前面,ORDER BY (event_time, user_id)能直接砍掉几个数量级的读取行。这一步没做好,后面全白搭。
② 分区策略——按时间PARTITION BY toYYYYMM(t),让旧数据整分区跳过。但别分区太碎,月分区通常够用,按天分区会让小文件和小 part 泛滥。
③ 二级索引选型——minmax 还是 bloom_filter?规则一句话:数值、日期、UUID 这类有序列用minmax(跳过整个 granule 的 min/max 判断);高基数等值过滤的字符串列用bloom_filter,它只为等值和 IN 服务,范围查询帮不上忙。一行建索引:
ALTER TABLE logs ADD INDEX idx_user user_id TYPE bloom_filter GRANULARITY 4;④ 压缩 Codec 与 join_algorithm——高基数字符串列默认 LZ4 换ZSTD(3),通常能省 30%+ 存储且查询侧解压开销可接受;低基数字符串列套LowCardinality或Delta+ZSTD。JOIN 侧把join_algorithm从 default 改成parallel,多表大 JOIN 在多核上通常能再快 30%~100%,小表灌进GRACE_HASH/HASH的内存上限也要注意,溢盘了性能会断崖。
顺序很重要:先动 ①②(数据模型),再动 ③④(查询参数),反过来做大概率白干。
把性能回归挡在合码前:query_log + CI 冒烟基准
线上侧靠system.query_log建一条每日慢查询巡检:elapsed_us超过基线 3 倍的 query 拉出来人工过一遍,比盯 dashboard 有效。
真正值钱的是把基准测试推进 CI。ClickHouse 自己的做法可以直接抄:tests/performance/ 下每个.xml就是一个自包含的性能用例——<create_query>建表、<fill_query>灌数、<query>是要计时的基准查询,跑在两台机器上(master 参考版本 vs 你的分支),输出是带统计显著性检验的对比报告,性能回退会直接在 PR 上标红。你不需要搭这么重的系统,最小可行版本是:
- 挑 5~10 条覆盖"聚合/JOIN/点查"的真实查询写成冒烟基准,每次合码前在固定规格的机器上跑一轮(单连接 + 16 并发各一组)
- 只比 P50 和 P99 相对基线的变化,超过 10% 就挂
- 数据准备、预热轮次、参数全部固化进脚本,谁也别手动改
性能测试不是发布前的一次性动作,而是把"慢查询"变成可复现、可对比、可拦截的工程问题。想继续深入,按这个顺序看:tests/performance/README.md(性能测试怎么写、怎么跑)、tests/benchmarks/README.md(TPC-H/TPC-DS 套件结构)、docs/en/operations/utilities/clickhouse-benchmark.md(benchmark 工具全参数)。跑一轮自己的数字,比读十篇对比文有用。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
