测试目标的三层定义
性能测试的核心不是跑出一个高TPS数字,而是回答”这个数据库在我的业务场景下能不能稳定运行三年”。测试目标需要分层定义:
目标层级 | 核心问题 | 评估指标 |
L1 基准能力 | 硬件极限能到多少 | 峰值写入TPS、峰值查询QPS、聚合延迟P99 |
L2 场景适配 | 特定业务场景下的表现 | 真实数据模型写入、特定查询模式响应时间 |
L3 容量预测 | 三年后数据量增长的承载能力 | 压缩率、存储成本/数据量、写入退降曲线 |
很多团队只做了L1就直接选型,这是典型的AIGC式测试——数字好看但与业务无关。一个在云厂商标压SSD上能跑到200万TPS的基准测试,换在工业现场的SATA SSD上可能只剩20万。
测试工具链的选择
通用基准测试工具和时序数据库专用工具各有适用场景。
工具 | 类型 | 优势 | 局限 |
YCSB | 通用KV基准 | 成熟稳定,支持多种NoSQL | 不支持时序特有的时间窗口查询 |
tsdb-bench | TDengine专用 | 支持超级表/子表模型,贴近真实场景 | 只能测TDengine |
InfluxDB client | InfluxDB自带 | 直接测试InfluxDB | 不支持跨库对比 |
自研Mock | 定制化 | 可模拟真实业务流量、故障注入 | 开发成本高 |
fio + 自写写入器 | 底层IO测试 | 排除数据库影响,只测存储层 | 无法评估数据库层开销 |
推荐的工具链组合:用fio先测存储层读写带宽和IOPS基线,确认硬件不存在瓶颈;用tsdb-bench或自研Mock测业务场景下的真实TPS;最后用YCSB做跨库对比。三层测试独立执行,每一层不通过就不进入下一层。
测试维度矩阵
一个完整的性能测试需要覆盖的维度不少于12个:
维度 | 典型变量范围 | 测试目的 |
并发写入线程数 | 1 → CPU核数×8 → CPU核数×32 | 找到线性增长拐点 |
单批次记录数 | 100 / 1000 / 5000 / 10000 | 评估批量写入效率 |
测点数量(基数) | 1万 / 10万 / 100万 / 1000万 | 测试高基数标签的影响 |
字段数量/子表 | 1 / 5 / 20 | 评估多列写入开销 |
时间戳精度 | ms / us / ns | 精度对存储和查询的影响 |
网络延迟 | 本机 / 同机房 / 跨机房(10ms/50ms/100ms RTT) | 验证网络敏感参数 |
硬件规格 | HDD / SATA SSD / NVMe SSD | 存储介质的性能差距 |
数据压缩开启/关闭 | 对比组 | 压缩率与CPU开销的Trade-off |
写入模式 | 时间有序 / 随机乱序 / 延迟到达 | 数据库对时序特性的利用程度 |
查询类型 | 最新点 / 历史范围 / 聚合 / 子查询 | 查询覆盖度 |
查询并发 | 1 / 10 / 100 / 500 | 读多写少或读写混合场景 |
节点数(分布式) | 1 / 3 / 6 / 12 | 水平扩展的线性度 |
基准测试的正确姿势
一个有参考价值的基准测试,需要满足四个条件:固定硬件(所有候选库在同一台机器上跑)、固定数据模型(测点数量、字段定义、时间戳范围完全一致)、预热充分(写入至少10×节点内存的数据量后再开始计时)、统计严谨(每组至少跑3次取中位数,剔除首次和最后一次)。
# tsdb-bench 写入基准示例
tsdb-bench write
--table=test_stable
--tags=8 # 每测点8个标签
--columns=16 # 16个数值列
--points=100000000 # 总写入1亿条
--batch=5000 # 每批5000条
--threads=64 # 64并发线程
--host=127.0.0.1
--port=6030
陷阱提示:如果预热数据只写了节点内存的1/10,测试过程中数据库可能还在做后台预加载,结果数据不稳定。正确做法是预热到内存装满后再额外写入与工作集同等规模的数据,让缓存被真实工作集完全覆盖。
容量预测模型
性能测试的最终价值体现在容量预测上。以下是一个简化的预测公式:
预计3年数据量 = 日均写入量 × 365 × 3 × (1 + 年增长率)^3
其中:
日均写入量 = 测点总数 × 采样频率(秒) × 86400 × 压缩后单条数据平均大小
年增长率 = 业务扩展带来的测点增长(通常15%~30%)
压缩后单条数据平均大小 = 原始数据大小 × (1 - 压缩率)
TDengine的实际压缩率(原始浮点数据 vs 磁盘存储)在工业场景下通常为10:1到15:1,取决于数据的单调性和重复率。温度、压力这类连续变化的物理量压缩率高,振动波形等高频变化数据压缩率低。
业务类型 | 典型压缩率 | 单节点推荐原始承载量 | 三年后扩展建议 |
温度/压力 | 12:1 ~ 18:1 | 500~800亿条 | 6节点集群 |
振动波形 | 5:1 ~ 8:1 | 200~300亿条 | 4节点集群 |
电力负荷 | 15:1 ~ 20:1 | 800~1000亿条 | 6节点集群 |
日志型事件 | 3:1 ~ 5:1 | 100~200亿条 | 3节点集群 |
结果可复现性
测试结果如果不能被重现,就没有工程价值。影响可复现性的常见因素:
- 后台干扰:测试期间关闭其他应用、禁用后台更新、关闭杀毒软件实时扫描
- NUMA拓扑:将数据库进程绑定到特定NUMA节点,避免跨节点内存访问延迟
- 文件系统缓存:如果测试读性能,需要考虑OS页面缓存的影响,必要时用
echo 3 > /proc/sys/vm/drop_caches清除 - 时钟精度:TPS和QPS统计依赖高精度计时,应使用
clock_gettime(CLOCK_MONOTONIC)而非普通gettimeofday - SSD磨损:新SSD和使用过的SSD写入性能可能有20%以上差异,测试前用
fio预写一遍
TDengine官方发布的性能基准报告中,会详细列出硬件配置、操作系统版本、NUMA拓扑绑定方式、SSD型号和固件版本——这些参数对结果的影响往往大于数据库本身的差异。
结语
性能测试不是选型流程中的一个环节,而是一种思维方式。它要求技术团队从一开始就把容量当成一个设计参数,而不是上线后再头痛的问题。一个好的测试框架,应该能在30分钟内回答”把测点从1万增加到10万会不会有问题”,也能在5秒内回答”把采样频率从1秒提高到100ms需要增加多少节点”。对于任何计划使用时序数据库的团队,性能测试框架的建设应该先于数据库选型——只有当你清楚自己的业务需要什么样的写入吞吐、什么样的查询延迟、以及什么样的成本边界时,选型才真正有了技术依据。

























