公司动态
基准测试工具之你不知道的两三事 | 11. 性能测试与正确性验证有什么区别
一轮基准测试结束后我们通常最先看到的是吞吐量、平均延迟、P99 和失败数。如果吞吐足够高、失败数又是 0能否直接说明测试通过不能。性能测试回答的是“系统处理得多快”正确性验证回答的是“系统处理的结果是否符合预期”。一次请求返回成功只能说明客户端收到了一次成功响应并不能自动证明所有数据都以正确的设备、时间戳、类型和值落入数据库。这一篇结合 IoT Benchmark 的实际实现讲清性能与正确性应怎样分开测试又怎样合并为一个可信结论。1. 两类测试回答的是不同问题维度性能测试正确性验证核心问题系统能处理多快、多稳写入和查询结果是否符合预期常见指标吞吐量、平均延迟、P99、失败率、CPU、内存、磁盘与网络记录数、时间戳、设备与测点、数据类型、具体值、查询结果集合主要输入工作负载配置与环境配置可重复读取的预期数据集或可信参考结果典型结论“在当前并发和批大小下系统达到某性能区间。”“预期写入的记录均可查询且字段和值一致。”失败表现延迟抬升、吞吐平台、超时、资源饱和少行、多行、错值、错类型、时间戳偏移、重复或覆盖两者不是互相替代的关系。正确但很慢说明系统能力不满足业务目标很快但写错性能数字则失去了意义。是否同一轮测试性能证据正确性证据吞吐、P99、失败、资源数量、时间戳、类型、值正确性门禁通过性能结果可用于比较结果作废并定位原因2. 为什么“写入成功”仍可能写错客户端成功调用写入接口并不等于业务数据完全正确。实际测试中至少可能出现以下情况表面现象可能隐藏的问题请求返回成功批内部分记录被忽略客户端只看到整体响应。失败数为 0数据写入了错误设备、表、测点或时间分区。写入点数符合预期字段顺序、数据类型或具体值发生变化。查询能返回数据返回的是旧数据、重复数据或被相同时间戳覆盖后的结果。两个系统吞吐接近两边真正持久化的数据量或写入语义并不相同。因此写入正确性至少应核对四层数量正确预期多少行、多少点实际是否一致。定位正确设备、表、测点、标签和时间戳是否正确。内容正确类型、空值语义和具体值是否一致。查询正确点查、范围查询和聚合是否返回预期结果。如果测试还涉及重试、相同时间戳覆盖或乱序写入则应再增加重复、幂等和最终可见性检查。3. IoT Benchmark 的三段式验证流程IoT Benchmark 提供了generateDataMode、verificationWriteMode和verificationQueryMode。从代码看它们组成了一条“准备预期数据 → 写入数据库 → 查询核对”的流程。generateDataMode生成 FILE_PATH 下的数据、schema 与信息文件verificationWriteMode读取数据文件并写入数据库统计写入吞吐与延迟verificationQueryMode再次读取同一份预期数据按设备与时间戳查询数据库逐值核对并记录错误三个模式的职责并不相同模式主要职责它不能单独证明什么generateDataMode生成可复用的数据文件和 schema。不会把数据写入待测数据库。verificationWriteMode从FILE_PATH读取批次、注册 schema 并执行写入同时统计写入性能。写入结束本身不代表数据已经逐值校验。verificationQueryMode再次读取同一数据集构造验证查询并将查询结果与预期时间戳和值比较。不能替代高并发性能压测也不是所有数据库适配器都必然支持。这意味着若只运行verificationWriteMode并看到失败数为 0最多能说“写入调用没有被工具判定为失败”不能说“所有数据已经验证正确”。4. 验证查询在代码中怎样工作在verificationQueryMode下RealDataSetQueryClient会从数据文件中取得一个IBatch再构造VerificationQuery。这个对象同时携带目标设备及其测点 schema该批记录的时间戳每个时间戳对应的预期值。数据库适配器据此生成查询读取这些时间戳对应的数据并把返回值与预期值逐项比较。以当前 IoTDB 适配器为例代码还会对 BLOB、DATE 等类型做格式转换再进入比较。这一逻辑比简单的count(*)更严格因为“行数相同”仍可能包含错误值。但它也有明确边界验证覆盖范围取决于对应数据库适配器的verificationQuery实现接口默认实现会返回“不支持验证查询”。因此开始测试前应先确认所用DB_SWITCH对应的适配器确实实现了该能力。5. 一个必须检查的实现细节错误日志不等于失败计数按本文读取的本地版本de2f8f3fIoTDB 的验证查询在发现值不一致或返回行数不一致时会输出ERROR日志但只要查询过程本身没有抛出异常方法最后仍可能返回Status(true, point)。随后DBWrapper会把Status.isOk()为真的操作计入成功测量。也就是说最终报告中的查询失败数为 0不足以证明逐值比较没有发现差异。因此正确性判定至少要同时查看证据应检查的内容验证日志是否出现Expected ... but was ...、预期行数不一致或查询错误。返回点数实际匹配点数是否等于根据数据集计算出的预期点数。数据集规模输入文件的设备数、记录数和测点数是否与测试方案一致。抽样复核手工或独立脚本查询若干设备与时间范围确认值和类型。服务端状态是否仍存在异步写入、后台处理或尚未可见的数据。这个细节并不意味着验证模式没有价值而是提醒我们日志和预期数量也是验证结果的一部分不能只看最终汇总表。6. 如何实际运行一轮验证首先准备一份固定数据集。可以使用generateDataMode生成也可以按 IoT Benchmark 要求准备FILE_PATH下的数据文件和 schema。# 第一步准备数据文件 BENCHMARK_WORK_MODEgenerateDataMode FILE_PATHdata/verification随后清理目标范围并写入同一份数据# 第二步写入验证数据同时获得写入性能 BENCHMARK_WORK_MODEverificationWriteMode FILE_PATHdata/verification CREATE_SCHEMAtrue IS_DELETE_DATAtrue写入完成后不要清理目标数据再切换为查询验证# 第三步查询并核对同一份数据 BENCHMARK_WORK_MODEverificationQueryMode FILE_PATHdata/verification示例只表达模式切换关系。实际运行时还应完整冻结数据库版本、DB_SWITCH、数据模型、批大小、客户端数、数据文件校验值和测试日志。7. 性能对比应该设置正确性门禁当比较两个版本、接口或产品时建议先定义门禁再生成性能排名。门禁通过条件示例写入调用门禁无未解释的超时和失败成功写入量达到预期。数量门禁设备、记录和数据点数量与固定数据集一致。内容门禁时间戳、类型和值的比较无差异。查询门禁关键点查、范围查询与聚合结果符合参考结果。可见性门禁在约定等待或刷新条件后数据对新查询可见。只有全部通过吞吐量和延迟才进入最终结果表。若某个系统更快但未通过正确性门禁应报告为“结果无效”或“当前配置下验证失败”而不是继续参与排名。8. 四个常见误区第一把失败数为 0 当作数据完全正确。失败数反映工具如何判定操作状态不一定覆盖逐值差异。第二只比较总行数。相同时间戳覆盖、错设备和错字段都可能让总量看似正常。第三性能测试结束后直接清库。如果还没有保存配置、日志并执行查询验证正确性证据会一并消失。第四一边验证一边随意更换数据集或 schema。预期数据必须固定否则比较对象本身已经发生变化。9. 小结性能测试关注吞吐、延迟和资源正确性验证关注数量、位置、类型和值。IoT Benchmark 可以通过生成数据、验证写入和验证查询三个模式组织这条流程但使用者仍需检查适配器支持范围、错误日志和预期点数。最稳妥的原则是先证明写对再讨论写快正确性门禁未通过的性能数字不参与比较。下一篇将继续讨论单机测试与集群测试的区别以及节点、网络和数据分布如何改变测试结论。系列文章第一篇数据库基准测试工具是什么第二篇从一次时序数据库写入测试开始第三篇如何模拟线上写入负载第四篇如何读懂测试结果波动第五篇什么是读写混合负载第六篇如何模拟线上读写混合负载第七篇怎样做一场公平的性能对比第八篇怎样找到并发与批大小的合理区间第九篇如何模拟乱序写入第十篇不同写入接口该怎样比较