基准测试最令人遗憾的结果,不是吞吐量低,而是几天后再看那张截图,已经说不清它来自哪个版本、哪份配置和哪台机器。
性能结果天然依赖上下文。同样的吞吐量,可能来自不同设备数、批大小、接口、数据库参数和硬件状态;同一个 P99 峰值,也可能对应客户端 GC、网络抖动、服务端合并或磁盘写满。没有原始证据,复盘只能变成猜测。
这一篇讨论怎样把一次 IoT Benchmark 运行保存为“可追溯实验包”,让结果不仅能看,还能复现、解释和审计。
1. 为什么只保存截图远远不够
截图通常只能保留某一刻的结果矩阵,却会丢失决定结果含义的条件。
| 只留下的内容 | 后来无法回答的问题 |
|---|---|
| 一张吞吐量截图 | 使用了哪个数据库版本和写入接口? |
一份config.properties | 服务端配置、硬件和网络环境是否相同? |
| 一个最终 CSV | 测试中途是否出现超时、重试或错误日志? |
| 一组监控曲线 | 曲线的时间窗口对应哪一轮 Benchmark? |
| 一句“测试通过” | 正确性验证检查了数量、时间戳还是具体值? |
真正可复盘的结果,必须能够重新建立“这一轮究竟发生了什么”的时间线。
2. 先给每轮测试一个唯一编号
不要使用“最终版”“再跑一次”或“test2”作为运行名称。一个实用的运行编号至少应包含日期、对象、负载和轮次,例如:
20260718-iotdb200-session-write-r03它可以映射为:
| 字段 | 示例 | 作用 |
|---|---|---|
| 日期 | 20260718 | 便于按时间定位环境变化。 |
| 被测对象 | iotdb200-session | 标明版本族或接口。 |
| 负载 | write | 区分纯写、混合、乱序等场景。 |
| 轮次 | r03 | 保留同一配置下的重复运行。 |
如果是多实例集群测试,还应为每个客户端增加实例后缀,如client-0、client-1,并由一个总运行编号把它们关联起来。
3. 建立一份可追溯实验包
下面是一种建议目录。它不是 IoT Benchmark 自动生成的固定格式,而是测试者在工具输出之外建立的归档约定。
runs/20260718-iotdb200-session-write-r03/ ├── README.md # 测试问题、结论与异常摘要 ├── manifest.yaml # 运行编号、时间、机器和版本 ├── config/ │ ├── benchmark.properties # 本轮实际使用的完整配置 │ └── database.conf # 与结论相关的服务端配置 ├── output/ │ ├── benchmark.log # 完整客户端日志 │ └── test-result.csv # 最终结果与配置快照 ├── monitor/ │ ├── client/ # 压测机 CPU、网络、GC 等 │ └── server/ # 每个数据库节点的资源记录 ├── correctness/ │ ├── verification.log # 验证日志 │ └── checks.md # 预期量、实际量与抽样结果 └── checksums.txt # 关键数据集和文件校验值这个目录最重要的原则是:原始证据与人工结论分开保存。日志和 CSV 不应被手工“修漂亮”;异常解释放进README.md,必要的清洗或汇总则另存新文件,并说明生成方法。
4. IoT Benchmark 提供了哪些结果出口
在当前配置中,至少要区分两类 CSV 能力。
4.1CSV_OUTPUT:保存最终结果和配置
CSV_OUTPUT=true当前代码会把配置、结果指标和延迟统计写入data/csvOutput/下的测试结果文件。它适合保存一轮结束时的最终汇总,也是最轻量的归档方式。
4.2TEST_DATA_PERSISTENCE:持久化测量结果
TEST_DATA_PERSISTENCE=CSV RECORD_SPLIT=true RECORD_SPLIT_MAX_LINE=10000000 REMARK=write_baseline_r03TEST_DATA_PERSISTENCE支持None、IoTDB、MySQL和CSV。选择 CSV 时,工具会通过CSVRecorder保存测量记录;选择数据库时,则需要配置对应的结果库地址、端口、库名、账号和连接参数。
二者不要混为一谈:CSV_OUTPUT=true负责输出最终测试结果 CSV;TEST_DATA_PERSISTENCE=CSV走的是测量结果持久化路径。是否两者都开启,取决于你需要“最终摘要”还是“更细的过程记录”。
| 需求 | 建议配置 | 说明 |
|---|---|---|
| 只保留最终结果与配置 | CSV_OUTPUT=true | 简单,适合小规模手工测试。 |
| 保存更细的测量记录 | TEST_DATA_PERSISTENCE=CSV | 便于分析不同操作和时间段。 |
| 多轮集中查询结果 | TEST_DATA_PERSISTENCE=IoTDB或MySQL | 需要单独维护结果库和标识。 |
| 只看终端或日志 | TEST_DATA_PERSISTENCE=None | 仍建议额外归档完整日志和配置。 |
配置中的账号和密码不应原样进入公开实验包。可以保存一份脱敏副本,同时在受控位置保留实际运行配置。
5. 用REMARK和打印间隔增强可追踪性
REMARK会参与结果标识或表名构造,适合放入简短、无特殊字符的运行标签:
REMARK=iotdb200_session_write_r03 # 保留必要的进度和中间结果 IS_QUIET_MODE=false LOG_PRINT_INTERVAL=5 RESULT_PRINT_INTERVAL=60中间结果不是最终结论,但它能帮助建立时间线。例如第 180 秒开始 P99 上升,而同一时刻某个节点磁盘写入等待升高,就比“整轮平均值变差”更容易定位问题。
设置打印间隔时也要控制日志量。过密的日志可能产生额外开销;过疏则可能错过短时异常。最稳妥的做法,是在正式对比前固定间隔,并让所有候选对象使用相同配置。
6. 配置、版本和环境要保存到什么粒度
仅保存 Benchmark 配置还不够。一轮测试至少应记录下面这些信息:
| 类别 | 必须记录 | 推荐补充 |
|---|---|---|
| Benchmark | Git 提交或发布版本、DB_SWITCH、完整配置 | Java 版本、启动方式、客户端日志级别。 |
| 数据库 | 产品版本、提交或镜像摘要、关键服务端配置 | 驱动版本、插件版本、后台任务状态。 |
| 数据 | 数据来源、设备数、测点数、类型、时间范围 | 输入文件校验值、乱序比例与随机种子。 |
| 硬件 | CPU、内存、磁盘类型与容量、机器数量 | NUMA、文件系统、挂载参数。 |
| 部署 | 单机或集群、节点角色、副本和分片设置 | 容器限制、网络拓扑、访问入口。 |
| 时间 | 开始与结束时间、时区、预热与正式阶段 | 各机器时钟同步状态。 |
版本最好记录为不可变标识,例如 Git commit、容器镜像 digest 或完整构建号,而不是只写“最新版”。数据库配置也应保存本轮实际生效值,不能只链接一份后来可能被修改的公共配置。
7. 资源监控必须与运行时间对齐
资源曲线只有和 Benchmark 时间线对齐后才有解释力。多机测试尤其要确认时区和系统时钟一致,并保存以下关键时间点:
- 数据库启动或重启完成时间;
- 预热开始与结束时间;
- 正式运行开始与结束时间;
- 异常、超时或人工操作时间;
- 正确性验证开始与结束时间。
如果测试期间发生了清库、重启、扩容或参数修改,必须记入时间线。这类操作不能只写在聊天记录里,否则之后无法判断曲线变化来自系统还是人工干预。
8. 怎样复盘一轮测试
复盘不应从“吞吐量是多少”开始,而应按证据门禁逐层推进。
第一步:确认实验身份
检查运行编号、候选对象、配置摘要、开始结束时间和结果文件是否互相对应,防止拿错轮次。
第二步:检查完整性与正确性
确认进程是否正常结束,成功与失败点数是否符合预期,验证日志是否存在值或行数差异。正确性未通过时,性能结果应标记为无效。
第三步:观察稳定阶段
把预热、正式运行和收尾阶段分开。平均吞吐量不能掩盖正式阶段内部的持续下降、周期抖动或长尾恶化。
第四步:关联资源和事件
将 P99、失败数与客户端 CPU、服务端 CPU、磁盘、网络、GC 和后台任务放在同一时间轴上。相关性可以帮助定位,但仍不能直接当作因果结论。
第五步:与同配置多轮结果比较
确认当前结果是否落在稳定范围。若只在某一轮异常,应先解释环境和状态差异;若多轮都出现相同变化,才更接近可重复现象。
9. 一份复盘摘要应该怎样写
一个合格的README.md不需要很长,但应包含以下内容:
# 运行摘要 - 运行编号:待填 - 测试问题:待填 - 被测对象与版本:待填 - 唯一变量:待填 - 正式运行窗口:待填 - 正确性门禁:通过 / 未通过 / 未执行 ## 主要结果 - 各操作成功点数、失败点数:待填 - 吞吐量与 P99 的多轮范围:待填 - 客户端与服务端资源峰值:待填 ## 异常时间线 - 时间点—现象—相关日志—相关资源:待填 ## 结论与边界 - 当前证据支持的结论:待填 - 尚不能覆盖的场景:待填 - 下一步复测条件:待填“未执行”比空白更好,因为它明确告诉读者哪一类证据缺失。若某项数据来自人工计算或二次汇总,也应注明来源文件和计算口径。
10. 四个常见误区
第一,只保存最好的一轮。异常轮次同样重要,它能揭示稳定性和环境敏感性。
第二,测试结束后再凭记忆补配置。运行前就应复制实际配置并生成运行编号。
第三,把监控截图当原始数据。截图适合展示,原始时间序列才适合复盘和重新计算。
第四,修改原始日志后不留痕迹。任何过滤、聚合和清洗都应生成新文件,保留原始证据。
系列文章
- 第一篇:数据库基准测试工具是什么
- 第二篇:从一次时序数据库写入测试开始
- 第三篇:如何模拟线上写入负载
- 第四篇:如何读懂测试结果波动
- 第五篇:什么是读写混合负载
- 第六篇:如何模拟线上读写混合负载
- 第七篇:怎样做一场公平的性能对比
- 第八篇:怎样找到并发与批大小的合理区间
- 第九篇:如何模拟乱序写入
- 第十篇:不同写入接口该怎样比较
- 第十一篇:性能测试与正确性验证有什么区别
- 第十二篇:单机测试与集群测试有什么不同
- 第十三篇:怎样保存和复盘一轮测试
- 第十四篇:一份可复用的基准测试方案模板