性能测试常见指标的含义

记得那次团队做性能测试,选了个周末,大家都在会议室里忙碌。
我负责监控TPS,看着屏幕上的数字,心里有些紧张。
那是一个周五的下午,地点在公司的新办公区,我们刚完成了一个新系统的上线。
当时,TPS稳定在3 00左右,我看着这个数字,心里想着,如果能在高峰时段保持这个水平,那也算是个不错的成绩了。

突然,系统开始出现波动,TPS从3 00跌到了2 00,然后又反弹到4 00。
我赶紧调整了监控图表的刷新频率,想看清楚是哪个环节出了问题。
就在这时,我注意到响应时间也跟着波动,最高达到了2 秒。
我马上想到,是不是我们的数据库出了问题?
我赶紧叫来数据库管理员,他检查了一下,发现是数据库的缓存满了,导致查询响应时间变长。
他清空了缓存,TPS和响应时间很快就恢复了稳定。
那天晚上,我们一直忙到深夜,才完成了所有的测试工作。

现在回想起来,那次经历让我深刻理解了TPS和响应时间的重要性。
它们不仅是性能测试的核心指标,更是衡量系统是否稳定的关键。
等等,我还记得那次测试,我们的并发用户数达到了5 00,但并发线程数只有1 00,这让我突然想到,是不是我们的并发策略还有优化的空间呢?

为什么MySQL单表不能超过2000万行?

哎哟,这MySQL单表超过2 000万行后性能下降的问题,其实挺复杂的。
我之前在做技术支持的时候,遇到过不少类似的案例。
说实话,我当时也没想明白,现在慢慢梳理一下。

首先,咱们得知道,MySQL的B+Tree索引结构,这玩意儿叶子节点存数据,非叶子节点存主键和页面号映射。
比如说,主键长度8 字节,页面偏移4 字节,那非叶子节点每条映射关系就占1 2 字节。
默认1 6 KB页面,大概1 5 KB能用,能存1 2 8 0条映射关系,叶子节点每行1 KB,能存1 5 条数据。

咱们算一下,三层B+Tree能存2 4 5 7 .6 万条数据,四层能存3 1 .4 亿条数据。
所以,数据量到2 000万行,索引深度一般也就3 层,不会因为深度增加导致性能下降。
现在硬件也进步了,SSD的IOPS过万,服务器内存能达到TB级,所以IO也不是根本问题。

但问题出在哪呢?主要是SMO(Sorted Merge Operation,有序合并操作)的并发控制缺陷。
这SMO操作不是原子化的,结构调整(比如节点分裂、合并)要改多个节点。
InnoDB引擎用乐观锁和悲观锁控制并发,乐观锁对根节点加S锁,非叶子节点加S锁,叶子节点修改不引发结构变动,就加X锁。
悲观锁的话,叶子节点修改触发SMO,得重新遍历B+Tree,对根节点加全局SX锁,从根节点到可能修改的节点加X锁。
这个过程,根节点得一直持有SX锁,其他操作就得等着,这就导致串行执行,并发性能受限。

再来说说索引组织表的特性,叶子节点扇出值低,1 6 KB页面,每行数据1 000字节,每个叶子节点只能存1 6 行数据。
这扇出值低,导致SMO触发更频繁,进一步放大了SMO无法并发写的缺陷。

那有解决方案吗?B-LinkTree优化了一下,中间节点增加link指针,节点内增加highkey字段,并发写优化。
还有,数据库选型也很关键,开源MySQL适合主键查询为主的简单业务,而像华为云GaussDB这种,采用B-LinkTree和堆组织表,在复杂商业场景下性能和并发能力更优。

所以说,MySQL单表超过2 000万行后性能下降,主要还是SMO并发控制缺陷和索引组织表的扇出值低问题。
通过优化索引结构或者选择合适的数据库架构,可以缓解这个问题。
不过,这事儿挺复杂的,得具体问题具体分析。

技术分享 | 如何计算 MySQL 的 QPS/TPS

那天,我在公司的小会议室里,和团队一起分析数据库的性能报告。
屏幕上,QPS和TPS的数据跳来跳去,就像股市的K线图。
我随手抓起一张纸,开始计算QPS,用的是方法二,从showglobalstatus里提取数据,算了一笔,发现QPS达到了2 000,挺高的。
然后,我转过头去问旁边的小张:“小张,你那边TPS怎么样?”他挠了挠头,说:“我正在用方法一,增删改查加起来才1 000多,是不是有点低啊?”我沉默了一会儿,突然想到,等等,还有个事,我之前在培训的时候学过,GTID这个方法挺有意思的,不知道我们这数据库支持不支持。