做数据库选型或者接手一套新数据库的维护时,我最常被问到的问题是:"YashanDB到底行不行?"而"行不行"这个判断,落到技术层面,其实就是一套可量化的性能指标在说话。去年底我完整地做了一轮YashanDB的性能评估,从环境搭建到压测工具选型,再到六个核心指标的逐项拆解,踩了坑也沉淀了不少经验。这篇就把我这轮评估的完整思路和方法摆出来,不讲虚的,全是怎么测、怎么读数、怎么判断的实操内容。
1. 把YashanDB摆上测试台之前,我先准备了这几件事
性能评估最怕的结果不是"性能差",而是"数据不可信"。一套做出来连自己都说服不了的数据,拿到评审会上就是废纸。所以在正式压测之前,我把环境、工具、数据规模这三件事全部钉死,确保后面跑出来的每一组数据都有可比性和可复现性。
1.1 被测环境怎么搭才能得出可信数据
先说硬件。数据库压测对存储介质的敏感度非常高,我这次评估用的是NVMe SSD,建议不要用SATA盘或者网络存储,否则IO延迟会把CPU层面的性能差异彻底掩盖掉。资源配置上,我给的是一台16核32线程、64GB内存的物理机,操作系统是CentOS 7.9,文件系统直接用的XFS。机器上除了操作系统和监控Agent之外不跑任何业务,避免其他进程抢占CPU和内存。
接着是YashanDB本身的部署模式选择。YashanDB有单机、共享集群、分布式三种产品形态,我的建议是:第一轮评估一定先跑单机。原因很简单——单机模式下CPU、内存、IO的调用路径最短,所有的性能瓶颈都直接暴露在最底层。如果单机的基线数据都拿不到,直接上集群或者分布式,遇到性能问题你根本分不清是数据库引擎的问题还是网络同步、分布式协调带来的损耗。
内存参数是测试前必须调的。数据库的buffer pool(缓冲池)大小直接决定了缓存命中率,而缓存命中率又直接影响IO压力。我在YashanDB的配置中把数据缓冲区调到了物理内存的50%左右,日志缓冲区保持默认,然后重启实例让配置生效。这里有个容易忽略的点:改完内存参数后一定要查看系统日志确认配置加载成功,不要想当然觉得改了就生效。
提示:压测前先跑一条
SELECT 1 FROM DUAL确认连接正常,再用系统自带的状态视图查一下实例的启动时间和内存分配情况。先确认数据库是健康状态,再开始谈压测。
1.2 压测工具怎么选:不要一上来就TPC-C
很多人一说数据库压测就提TPC-C,但TPC-C的完整审计流程对环境和脚本的要求极高,适合厂商做官方背书,不适合工程师做日常评估。我的做法是分层测试:先用sysbench这类通用工具做基础的OLTP读写测试拿到第一轮数据,再用BenchmarkSQL或者自建脚本做贴近业务的复杂事务模拟。
为什么这么做?因为sysbench的优点是标准化程度高、参数可控、结果可复现,适合做横向对比;而BenchmarkSQL的事务模型更接近真实的订单、支付、库存场景,适合验证YashanDB在复杂SQL和事务并发下的表现。两轮数据结合起来,既能看到引擎的"理论极限",也能看到"业务贴近度"。
工具确定后,压测参数也要提前固定。比如并发线程数、单条事务的SQL复杂度、测试时长、预热时间,这些必须写进测试方案里。我专门建了一个压测参数清单,每次跑完都把当时的参数贴在结果旁边,省得后面分析数据时还要回忆"当时用的是多少并发"。
1.3 数据规模和冷热分离的讲究
压测数据量不是越大越好,而是要和内存大小形成合理比例。我的原则是:基础数据量是内存缓冲区的2到4倍。比如64GB内存、分配了32GB给buffer pool,那基础数据就准备80GB到128GB。这样保证一部分数据常驻内存,一部分数据需要从磁盘读取,才能真实反映数据库混合读写的表现。
测试表的字段设计也别偷懒。我建了用户表、订单表、商品表三张核心表,用户表500万行,订单表3000万行,商品表50万行。索引尽量贴近真实业务的组合索引和普通索引混合。数据一次性灌完后,先跑一轮全表扫描的查询作为预热,让热门数据页真正进到缓存里。预热不充分的后果很直接:前面的数据会偏低,而且波动大,整个结果没法用。
2. 第一对指标:吞吐量和响应时间,必须放在一起读
这大概是性能评估里最核心的一对指标了。但实际工作时我看到太多人只盯着TPS一个数,忽略了响应时间的分位数,最后对系统性能的判断严重失真。
2.1 TPS和QPS:数据库每秒到底干了多少活
先分清两个概念:TPS是每秒完成的事务数,一个事务可以包含多条SQL语句;QPS是每秒处理的查询请求数,通常按单条SQL来算。对OLTP业务来说,TPSC是更重要的指标,因为它衡量的是完整业务动作的完成能力;QPS更适合评估读写分离架构下只读节点的查询能力。
我在YashanDB的评估中,对sysbench的OLTP读写测试取TPS,对只读测试取QPS。实测下来,在16核环境下单机YashanDB的TPS表现处于主流数据库的正常区间,具体数值受数据规模和并发数影响很大,不建议直接拿网上的跑分做对比。跑分对比必须满足两个前提:一是测试环境硬件一致,二是数据规模、参数配置一致。缺一个,对比就是耍流氓。
2.2 响应时间:用户感受到的"快"和"慢"
响应时间上我常看四个数:平均值、p50、p99、p999。平均值最容易骗人——一个系统如果99%的请求都在10毫秒内完成,但1%的请求因为锁等待或者IO抖动跑到2秒,平均值可能只有30毫秒,表面看完全正常,实际上用户体验已经很糟糕了。
p99的意义在于排除掉那1%的极端异常后,绝大多数请求的响应上界在哪里。p999则是拔高到千分之一的极端场景,适合对延迟极敏感的金融类交易。压测YashanDB的OLTP场景时,我习惯同时记录这四个数。如果p50低但p99突然高出一两个数量级,大概率是测试过程中出现了锁竞争、日志切换或者缓存未命中的抖动,这些信号后面逐条排查。
2.3 高吞吐和低延迟不能兼得时,怎么权衡
这里有个业务上的取舍问题。在评估阶段,我会把两个指标分开看:先测出规定的并发下能做到的最大吞吐,再测出在严格延迟约束下的吞吐上限。比如设定"p99必须在50毫秒以内"的约束,看这个约束下TPS能到多少;再把约束放宽松到200毫秒,看TPS能提升多少。这个差值就是延迟指标对应的性能成本。
实际上,数据库本身的调优也能影响这对指标的平衡。缓冲池大小、日志刷新频率、是否开启自动提交、索引设计是否合理,都会同时影响两个指标。测试过程中我调整过几次YashanDB的日志提交策略,发现对延迟的影响非常明显。这类调整要不要做,完全看业务场景——如果业务允许一点数据丢失窗口,可以换更高的吞吐;如果业务要求强一致,就必须牺牲部分吞吐。压测就是要通过这种调节把系统的能力边界摸清楚。
3. 第二对指标:并发能力和资源消耗,一个看上限一个看代价
吞吐和延迟是数据库的"外部表现",但光看外部表现不够,我接着挖了两层:系统承受并发时的实际能力上限,以及为这个上限付出的资源代价。
3.1 并发爬坡测试:线程数不是越多越好
并发能力的测试方法我习惯用"爬坡法":从1个并发线程开始,依次加到4、8、16、32、64、128、256,每个档位固定跑5分钟,记录该档位下的TPS和响应时间,最后把数据画成曲线。
这条曲线的形状能说明很多问题。理想情况下,TPS应该随并发数线性增长,然后增速放缓,到某个点达到峰值,之后继续加并发TPS持平甚至下降。如果128线程和256线程的结果几乎一样,说明系统已经到瓶颈,加线程只是增加无谓的上下文切换。如果并发一旦超过32就剧烈下降,那大概率是锁竞争或者连接池配置不当。
我在YashanDB上观察到的情况是:并发在64以内时,吞吐量增长接近线性;从128开始增速放缓,但曲线仍然稳定,没有出现明显的断崖式下跌。这说明它的锁机制在多线程扩展上做得比较稳健。不过要注意的是,这轮的测试数据是在单机16核环境下拿到的,换到更大规格的机器或者集群环境,曲线形状一定会变,所以并发测试一定要在目标生产规格的环境上重复,不能拿低配环境的结论去推断高配。
3.2 资源账怎么算:CPU、内存、IO三项消耗逐一盘
跑完并发测试,我会同时盯着三张报表看:CPU利用率、内存使用、磁盘IO。
CPU是最直观的。压测时我先看整体CPU使用率,再看核心是否均匀。合理的状态是所有核心占用率大致接近,如果出现个别核打满、其他核空闲,那是典型的单线程瓶颈,比如某个热点字段的锁串行化。YashanDB在并发场景下的CPU均衡性不错,但这不是天生保证的——如果某条SQL写得很烂、走了全表扫描,照样能把单核拉满。
内存看的是两件事:进程常驻内存是否稳定增长,以及缓冲池命中率。缓存命中率我会用数据库状态视图直接查,正常情况下OLTP混合读写命中率应该在95%以上。如果命中率跌到90%以下,说明缓冲池配小了或者数据访问模式极度分散,这时优先调内存而不是怀疑SQL。
磁盘IO的关注点不是带宽,而是延迟和队列深度。用iostat观察await和util两个值:await表示IO响应延迟,正常应该在几毫秒到十几毫秒;util超过90%说明磁盘接近饱和。我在压测中故意把数据量做得超过内存,目的就是让一部分随机读真实落盘,从而观察磁盘在随机IO下的真实表现。
提示:压测过程中每5秒采样一次资源数据,防止只看到结束时的瞬间状态。有些性能问题是在测试中段出现的,结束后去看top已经看不到任何痕迹了。
3.3 资源的"代价"最终要换算成成本
资源消耗指标的终极意义是算成本。一台16核的机器跑出3万TPS,和一台8核的机器跑出2.8万TPS,虽然大机器看起来性能更好,但如果业务只需要2万TPS,那8核机器一台就够,省下的硬件成本是实打实的。
我在评估报告里会把资源消耗归类成两类:可压缩成本和不可压缩成本。CPU和内存是可通过SQL优化、参数调优来压缩的;磁盘IO的延迟瓶颈最难压缩,一旦随机IO成为瓶颈,通常只能靠加缓存或者换更快的存储介质来解决。这样分类的好处是,给业务方提建议时可以直接说:要提升性能,优先优化哪些SQL、调哪些参数,而不是一句"建议加机器"了事。
4. 第三对指标:稳定性和扩展性,短跑和长跑的差距
如果说前两对指标是"短跑成绩",那稳定性和扩展性就是"长跑耐力"。数据库选型最怕的就是短跑满分、长跑不及格——峰值性能好看,跑上半小时就开始掉链子,这种系统上线就是灾难。
4.1 稳定性测试:一小时起步,重点盯波动曲线
我跑稳定性测试的习惯是至少连续压测1小时。短于这个时间,很多慢性问题根本来不及暴露。测试期间持续记录TPS、响应时间、错误率三个数据,重点看它们的波动情况。
一个稳定的系统,TPS曲线应该是围绕均值小范围波动的。如果曲线出现周期性的凹陷,找一下凹陷的时间点是不是对应全量备份、日志切换或者统计信息自动收集——这些后台任务经常成为性能杀手。YashanDB在这轮长时间测试中,有一个值得说的表现:长时间压测下的TPS波动范围控制在很小的区间内,没有出现明显的性能衰减或内存持续攀升。内存持续攀升是我特别警惕的信号,那通常意味着某个对象没有被及时释放,长时间跑下去就是OOM。
稳定性测试的另一个观察点是慢SQL的增长。压测开始阶段如果出现几条慢SQL,可能是冷数据首次访问导致的缓存未命中;但如果慢SQL数量随着时间推移持续增加,那可能是缓存失效策略或者数据分布变化导致的,需要把测试期间产生的慢日志导出来逐个分析。
4.2 扩展性测试:加资源之后性能涨多少
扩展性测试解决的是预判问题:未来业务增长,这套数据库能不能扛得住。扩展性主要看两条线:纵向扩展是加CPU和内存,横向扩展是加节点。
纵向扩展的测试方法很简单,同一套压测方案分别跑在8核、16核、32核的机器上,看吞吐量是否等比例上升。但这个测试成本太高,我一般不做完整版,只跑16核和32核两组做推算。横向扩展则针对YashanDB的集群或分布式形态,从单机扩到三节点,再扩到五节点,看整体吞吐量是否接近线性增长。
需要清醒认识的是:没有任何数据库能做到完美的线性扩展。集群节点之间的数据同步、分布式事务协调、网络开销都会吃掉一部分性能。评估扩展性时我会算一个"扩展效率":扩展后吞吐量增量除以扩展的节点数。如果每加一个节点的增量不到单节点性能的70%,那就要考虑架构上是否有问题,还是业务的数据模型根本不适合分布式。
4.3 稳定性和扩展性,对选型决策的影响最大
这四个小时的测试跑完之后,我对YashanDB的总体印象是这样的:单机模式下的性能表现中规中矩,但胜在稳定;扩展性方面,共享集群和分布式架构的功能差异很明显,选型时不能只考虑性能指标,还要看业务系统的数据规模是否真的需要走分布式路线。如果业务数据量和并发量没有大到单机扛不住的程度,强行上分布式架构反而会引入不必要的复杂度,性能还可能不如深度调优后的单机。
5. 六个指标怎么合成最终结论:我的判断框架和几个容易忽略的坑
数据都拿到手之后,最后一步是把六个指标拼成一张完整的图。这也是评估工作里最容易被轻视的一环——很多人跑完数据就直接写"性能达标"或者"性能不达标",完全不管这些指标之间的内在关系。
5.1 指标的优先级不是固定的,取决于业务场景
六指标本身的权重因业务而异。OLTP在线交易系统,吞吐量和稳定性是首要的,p99延迟也必须有硬约束;OLAP分析类业务,处理速度比并发能力更关键,资源消耗的关注点也要从CPU转向IO带宽;混合负载场景则要在两对指标之间找平衡。
我习惯把评估结论分成三种:推荐、有条件推荐、不推荐。"推荐"意味着六项指标里关键项全部满足业务预期;"有条件推荐"意味着存在短板,但可以通过配置调整、SQL优化或者架构变通来弥补;"不推荐"则意味着硬伤无法绕开。YashanDB在这轮评估中,如果面向典型的OLTP业务场景,结论是"有条件推荐"——基础性能在线,但部分高级特性在不同产品形态下的表现差异较大,需要结合具体场景二次验证。
5.2 实测中常见的几个坑,每一个都是我踩过的
第一个坑是预热不充分。数据加载完就开跑,结果前面半小时都在做缓存填充,读出来的数据忽高忽低。解决方法是正式压测前先跑一轮只读查询来预热缓存,直到连续两次查询耗时接近再开始正式测试。
第二个坑是线程数拉得太高。很多人觉得并发线程越多越能测出性能上限,实际上一旦超过硬件的物理线程数,操作系统就开始做上下文切换,吞吐反而下降。判断方法很简单:观察"吞吐随并发增长停滞甚至下降"的拐点,那个拐点才是系统真实能力的边界。
第三个坑是只盯着峰值不看曲线。峰值只能说明系统在某一个瞬间的极限,完全不能代表持续服务能力。真正判断性能要看整条曲线的走势、波动幅度和异常点分布。我前面说的一小时压测就是为了补这个信息。
第四个坑是忽略连接池的影响。压测工具直接直连数据库和通过连接池访问数据库,结果差距很大。如果业务实际是通过连接池访问的,那压测也必须走连接池,否则测出来的结果没有参考价值。
5.3 选型评估的最终建议:永远要用自己的数据说话
做完这轮评估后,我自己最大的体会有两点。
第一,任何数据库的公开性能和网上跑分都只能当作参考坐标。同一款数据库,在不同硬件、不同负载模型、不同参数配置下的表现天差地别。只有用自己的业务数据、自己的SQL、自己的压测场景跑出来的成绩才算数。
第二,性能评估不是一次性的工作。数据库上线后随着数据量增长、业务模式变化,性能会持续漂移。我的做法是沉淀一套完整的压测脚本和参数基线,每季度做一轮基准回归,一旦发现关键指标偏离基线超过15%,就主动排查原因。这套流程的价值比单次评估大得多。
最后再分享一个实操细节:写性能评估报告时,我会把每次压测的完整参数、环境信息和原始数据全部存档,包括测试时间、工具版本、配置参数、数据量、每档并发的完整结果。这些看似琐碎的记录,在做前后对比和问题回溯时是救命的东西。评估的真正价值,从来不在结论本身,而在这套数据能不能支撑后续每一次决策和每一次疑问的解答。