4. 压测场景设计:单表查询压测、多表Join压测、聚合查询压测、写入压测、混合负载压测

压测场景设计,说白了就是回答一个问题:你的系统到底要在什么样的“炮火”下扛得住?

我见过不少团队,上来就用一个简单的 SELECT * 跑一遍,然后说“系统性能不错”。结果上线第一天,业务方一个多表 JOIN 就把集群打挂了。嗯,这种坑我踩过不止一次。

所以这一章,咱们把压测场景拆成五类:单表查询、多表 JOIN、聚合查询、写入、混合负载。每一类都有它独特的“脾气”,你得对症下药。

核心原则:压测场景必须覆盖生产环境的真实流量模式。不要只测“最爽”的场景,要测“最痛”的场景。

压测场景分类与关系 OLAP 压测场景 单表查询 多表 JOIN 聚合查询 写入压测 混合负载 场景设计要点: • 单表查询:关注点查、范围查、索引命中率 • 多表 JOIN:关注 Shuffle 策略、数据倾斜、内存溢出 • 聚合查询:关注 Group By 字段基数、窗口函数、内存压力 • 写入压测:关注写入吞吐、合并策略、磁盘 IO 瓶颈 • 混合负载:关注资源隔离、优先级调度、锁竞争

4.1 单表查询压测

单表查询是压测的“基本功”。别小看它,很多性能瓶颈其实就藏在这里。

我个人习惯把单表查询压测分成三个子场景:

  • 点查(Point Query):WHERE 条件精确匹配主键或索引。比如 SELECT * FROM orders WHERE order_id = '12345'。这个场景主要测索引查找效率。
  • 范围查(Range Query):WHERE 条件带范围过滤。比如 SELECT * FROM orders WHERE create_time BETWEEN '2024-01-01' AND '2024-01-31'。这个场景测的是扫描能力和 IO 吞吐。
  • 全表扫描(Full Scan):不带 WHERE 条件,或者条件无法下推。这个场景测的是存储层的顺序读取能力。

我的经验:点查的 P99 延迟如果超过 50ms,说明索引设计或者缓存策略有问题。我曾经在一个 ClickHouse 集群上发现点查慢,最后定位到是主键索引粒度太粗,调整后延迟从 200ms 降到了 5ms。

压测参数建议:

场景并发数数据量级关键指标
点查50 ~ 500千万级P99 延迟、QPS
范围查20 ~ 200亿级吞吐量(MB/s)、扫描行数
全表扫描5 ~ 50十亿级磁盘 IO 利用率、CPU 利用率

4.2 多表 Join 压测

多表 JOIN 是 OLAP 系统最“娇气”的场景。你想想看,两个大表一 JOIN,Shuffle 数据量可能翻好几倍,搞不好直接把网络打满。

我建议至少覆盖以下三种 JOIN 模式:

  • 大表 JOIN 大表:比如订单表 JOIN 用户表。这种场景最容易出现数据倾斜和内存溢出。
  • 大表 JOIN 小表:比如事实表 JOIN 维度表。这种场景主要测 Broadcast Join 的优化效果。
  • 多表级联 JOIN:3 张以上表连续 JOIN。这种场景测的是优化器的执行计划生成能力。

避坑指南:我曾经压测一个 5 表 JOIN 的场景,结果发现某个节点的内存直接飙到 90%。后来一查,是因为其中一个 JOIN 键的分布极度不均匀,导致单个 Task 处理了 80% 的数据。解决方案是加一层 Salting 或者调整 Shuffle 分区数。

压测时重点关注:

  • Shuffle 读写量(Shuffle Read/Write)
  • 数据倾斜比例(最大分区数据量 / 平均分区数据量)
  • GC 频率和 Full GC 次数

4.3 聚合查询压测

聚合查询是 OLAP 的“看家本领”。GROUP BY、COUNT DISTINCT、窗口函数,这些都是压测重点。

我个人习惯把聚合查询压测分成两类:

  • 低基数聚合:GROUP BY 字段的基数在几千以内。比如按省份、按天聚合。这种场景主要测 Hash 聚合的效率。
  • 高基数聚合:GROUP BY 字段的基数在百万级以上。比如按用户 ID、按商品 SKU 聚合。这种场景容易把内存撑爆,系统可能会走磁盘落盘。

还有一个容易被忽略的点——COUNT DISTINCT。这个操作在数据量大的时候非常吃资源。我建议压测时单独设计一个 COUNT DISTINCT 的场景,看看系统在 HyperLogLog 等近似算法下的表现。

关键参数:聚合查询的压测结果一定要关注“内存峰值”和“Spill 到磁盘的数据量”。如果 Spill 量超过总数据量的 10%,说明内存配置或者聚合算法需要优化。

4.4 写入压测

写入压测经常被忽略,但生产环境里写入往往是瓶颈。尤其是实时写入场景,写入速度跟不上,数据延迟就会越来越大。

写入压测要覆盖:

  • 批量写入:模拟离线导入,每次写入几万到几百万行。主要测写入吞吐和合并(Merge)性能。
  • 实时写入:模拟 Kafka 消费写入,每秒几百到几万条。主要测写入延迟和背压机制。
  • 并发写入:多个客户端同时写入同一张表。主要测锁竞争和事务冲突。

我的经验:有一次压测实时写入,发现写入延迟从 10ms 慢慢涨到 5s。排查后发现是后台合并线程把 IO 打满了,导致前台写入被阻塞。后来限制了合并线程的 IO 带宽,问题就解决了。

4.5 混合负载压测

混合负载压测是“终极考验”。生产环境从来不会只跑一种查询,往往是查询、写入、聚合同时进行。

我建议混合负载压测按以下比例设计:

负载类型占比(参考)说明
单表查询30%模拟日常报表查询
多表 JOIN20%模拟复杂分析场景
聚合查询20%模拟 BI 看板聚合
写入30%模拟实时数据接入

混合负载压测的核心观察点:

  • 资源争抢:CPU、内存、IO、网络,哪个先到瓶颈?
  • 查询延迟抖动:写入压力上来后,查询延迟是否大幅上升?
  • 写入积压:查询压力大时,写入是否出现背压或超时?

避坑指南:我曾经压测混合负载时,发现写入一上来,查询的 P99 延迟从 100ms 直接飙到 3s。后来定位到是资源隔离没做好,写入任务和查询任务抢同一个线程池。解决方案是给查询和写入分配独立的资源池,并设置优先级。

嗯,这五个场景基本覆盖了 OLAP 系统在生产环境可能遇到的大部分情况。压测场景设计不是一次性工作,你得根据业务特点不断调整。下一轮压测前,记得回顾一下上一轮的结果,看看哪些场景需要加码,哪些场景可以减量。