1模拟真实环境下的性能
再次强调的是,前面的测试数据都是性能测试,不能作为实际环境的性能数据,这些数据表现的应该是理想环境下的极限性能,其只能作为参考。
既然测试用例不完整,我们就考虑模拟一下真实的环境。
1.1压力测试
先准备检测一下MySQL在压力情况下的性能变化情况,测试的版本为MysQL4.0 gcc静态版本,使用的配置参数和原来相同。
我先在数据库中插入10000000条记录,然后我在另外一台机器机器上启动1组压力进程对数据库进行查询或者修改操作,测试的进程组包括10,50,100个读的进程,10,50,100个读写进程(读写各一半),这些进程的操作间隔时间为10000微秒(0.01秒执行一次)或者1000微妙(0.001秒执行一次)。其中0.01秒执行一次间隔的压力相对较轻,0.001秒执行一次间隔压力就比较重了,一般用mysqladmin processlist检查,大部分进程的状态都是执行状态。
同时在这台机机器(本机上)测试查询1000000条记录(总记录数的1/10)所耗费的时间。同时为了比较,使用vmstat记录相关的CPU占用率的情况。分别记录压力进程运行后,测试进程运行前后的CPU空闲率。
MyISAM 引擎的测试结果如下:
表1 MyISAM引擎的压力测试
测试项目
|
压力进程的操作间隔为0.01秒
|
压力进程的操作间隔为0.001秒
|
||||||
运行前CPU空闲(%)
|
运行后CPU空闲(%)
|
耗时(s)
|
处理速度(条记录/s)
|
运行前CPU空闲(%)
|
运行前CPU空闲(%)
|
耗时(s)
|
处理速度(条记录/s)
|
|
没有压力进程
|
100
|
69
|
258
|
3875.97
|
100
|
69
|
258
|
3875.97
|
10个读取压力进程
|
97
|
69
|
282
|
3546.10
|
85
|
57
|
318
|
4048.58
|
50个读取压力进程
|
88
|
59
|
316
|
3164.56
|
35
|
21
|
700
|
3333.33
|
100个读取压力进程
|
73
|
45
|
379
|
2638.52
|
22
|
10
|
2093
|
2283.11
|
10个读写压力进程(5读+5写)
|
94
|
67
|
247
|
3144.65
|
69
|
51
|
361
|
2770.08
|
50个读写压力进程(25读+25写)
|
80
|
54
|
300
|
1428.57
|
25
|
16
|
4206
|
237.76
|
100个读写压力进程(50读+50写)
|
59
|
37
|
438
|
477.78
|
27
|
25
|
大约需要200000
|
0.50
|
对于MyISAM引擎,最后一组测试我没能作完,实在是太慢了,在6个小时后我检查发现查询才进行到12477,我几乎崩溃,估计要让他跑完要5-6天,只好作罢。
比较的图表:

图2 MyISAM引擎的压力测试
通过比较,我们可以看出,在只有读取操作的压力下,MyISAM引擎表现还不错,在压力增加的情况下性能没有出现陡降。而对于读写的混合压力测试情况下,MyISAM引擎的表现急转直下,特别是最后的100个读写0.001s间隔压力进程测试情况下,速度已经不可接受。这是检查MySQL的状态计数变量Table_locks_waited数值非常大,而且远远大于Table_locks_immediate。这表示系统操作中,等待锁的操作非常多。
由于MyISAM引擎采用表锁,所以在读写压力测试下,由于写操作锁会阻塞所有的读取锁,而且优先基本大于读取锁,所以此时读取操作必须等待。而且由于最后的压力测试写操作频度很高,所以造成了几乎1秒1条的读取速度。而且值得注意的是此时CPU性能压力并不大,系统的能力并没有得以发挥。
为了横向比较MyISAM引擎和InnoDB引擎在不同压力的表现,我也测试了InnoDB在压力情况下的表现。
表2 InnoDB引擎的压力测试
测试项目
|
压力进程的操作间隔为0.01秒
|
压力进程的操作间隔为0.001秒
|
||||||
运行前CPU空闲(%)
|
运行后CPU空闲(%)
|
耗时(s)
|
处理速度(条记录/s)
|
运行前CPU空闲(%)
|
运行前CPU空闲(%)
|
耗时(s)
|
处理速度(条记录/s)
|
|
没有压力进程
|
100
|
69
|
278
|
3597.12
|
100
|
69
|
278
|
3597.12
|
10个读取压力进程
|
97
|
68
|
281
|
3558.72
|
94
|
65
|
387
|
4504.50
|
50个读取压力进程
|
86
|
58
|
312
|
3205.13
|
76
|
48
|
634
|
3690.04
|
100个读取压力进程
|
73
|
46
|
326
|
2583.98
|
54
|
28
|
892
|
2832.86
|
10个读写压力进程(5读+5写)
|
83
|
55
|
222
|
3067.48
|
72
|
45
|
276
|
3623.19
|
50个读写压力进程(25读+25写)
|
40
|
20
|
271
|
1577.29
|
4
|
2
|
1243
|
804.51
|
100个读写压力进程(50读+50写)
|
24
|
9
|
353
|
1121.08
|
3
|
1
|
4011
|
249.31
|
比较的图表:
图3 InnoDB引擎的压力测试
可以看出InnoDB引擎在压力测试面前表现得不错,基本上是随着压力的增加,速度呈现线性的下降(注意第2步测试的进程是50个为第一步的5倍)。
为了方便比较,我也给出InnoDB和MySQL的两个比较图表,必须指出的是,这样的比较意义有一定的局限性。因为并不能保证每个连接对于两种引擎的压力都一致。

图4 MyISAM和InnoDB的读取压力测试比较

图5 MyISAM和InnoDB的读写压力测试比较
从对比图表可以看出[注],InnoDB引擎可以更好的承担查询压力。
MyISAM 为了避免在大压力的环境下性能下降,可能必须将表分割的更细。
如果你够心细应该可以发现在加入0.01秒读写压力测试后,得到的性能反而提升了。?而且MyISAM引擎和InnoDB引擎的数据都有提升?这个现象非常有趣。为了验证不是干扰,我重新测试了一次InnoDB在这个情况下的表现,发现测试结果没有错误。我猜测这还是和查询的Cache有关,InnoDB将查询结果放入Cache可能是在提交操作时,而在在提交时发现同时有更改语句的情况下,InnoDB引擎没有将查询语句的结果放入Cache。由于减少了Cache的成本,而且相对而言此时的更改操作压力很轻,所以这样反而加快了查询的速度。
1.2多表访问环境模拟
前面测试的方式都是使用单张表进行测试,在多张表的情况下,MySQL的表现如何?我打算这样模拟,采用10张表,每张表存放5000000条记录,在另外一台机器上,每个进程都查询访问一个表,查询频率为0.005秒一次,查询记录为随机数选取,同时在本机上进行插入,查询,更改,删除1000000条记录的操作。
对于MyISAM引擎,同时由于增加了表的数量,调整了一些相关的参数,
set-variable = key_buffer_size=512M
set-variable = query_cache_size=128M
对于InnoDB引擎,仍然使用原来的配置,同时由于测试机器发生了更改[注],为了对比的公正性,我重新测试了没有压力(没有程序同时访问)情况下的对比数据。
表3 多表访问的环境模拟
参数配置
|
插入100000条记录耗时
|
处理速度(条记录/s)
|
查询100000条记录耗时
|
处理速度(条记录/s)
|
修改100000条记录耗时
|
处理速度(条记录/s)
|
删除100000条记录耗时
|
处理速度(条记录/s)
|
MyISAM引擎,
|
197
|
5076.14
|
333
|
3003.00
|
173
|
5780.35
|
175
|
5714.29
|
MyISAM引擎,模拟多表环境
|
209
|
4784.69
|
3366
|
297.09
|
566
|
1766.78
|
507
|
1972.39
|
InnoDB引擎,
|
221
|
4524.89
|
425
|
2352.94
|
255
|
3921.57
|
234
|
4273.50
|
InnoDB引擎, 模拟多表环境
|
520
|
1923.08
|
1853
|
539.67
|
677
|
1477.10
|
629
|
1589.83
|
对比图表为

图6 模拟多表访问的测试
在非模拟情况下,MyISAM 引擎有少量优势,但是在模拟环境下查询记录情况,MyISAM引擎的表现远慢于InnoDB的表现,对于这个我感觉有点奇怪,因为此时不应该有锁排队的情况发生。?
在压力情况下,MyISAM引擎的插入语句性能看似不错,但是这是由于在我的测试用例中,MyISAM引擎不用加入写锁锁定表。(见前InnoDB和MyISAM引擎的对比测试章节)
由于所有的操作都是顺序操作,而且没有加入写操作,感觉测试比较倾向于MyISAM引擎[注]。
测试的机器也是为380G3,但是内核为2.4.21,初步看来2.6内核的性能更好一些。
对这个模拟感觉不是太理想,模拟正式环境和测试极限速度这两者可能就有矛盾。
1.3网络访问速度
前面的测试基本都是基于本机操作访问数据库的操作,但是更多的应用是基于网络访问。所以也业考虑测试一下网络环境下MySQL访问速度。
基于网络的访问分为2种,一种是利用长链接,一种是短链接,就是每次访问都重新进行一次链接。
测试环境,数据库使用MyISAM引擎,使用Cache。网络带宽为100Mbps。
由于对于1个服务器,可以循环使用的SOCKET端口是有限,所以我只执行了20000次操作进行比较,由于测试的数据较少,对于这些数据比较差距就可以了。
比较项目
|
本地操作
|
网络操作
使用长链接
|
网络操作
使用短链接
|
网络操作(STMT)
使用长链接
|
||||
耗时(s)
|
处理速度(条/s)
|
耗时(s)
|
处理速度(条/s)
|
耗时(s)
|
处理速度(条/s)
|
耗时(s)
|
处理速度(条/s)
|
|
插入20000条记录
|
4
|
5000.00
|
13
|
1538.46
|
27
|
740.74
|
8
|
2500.00
|
查询20000条记录
|
4
|
5000.00
|
21
|
952.38
|
34
|
588.24
|
15
|
1333.33
|
改写20000条记录
|
4
|
5000.00
|
13
|
1538.46
|
29
|
689.66
|
8
|
2500.00
|
删除20000条记录
|
3
|
6666.67
|
13
|
1538.46
|
36
|
555.56
|
7
|
2857.14
|
比较图表如下:

图7 网络环境性能下的测试
对于网络的访问,网络长链接的访问速度是本地执行速度的3-4倍(降低了60%),网络短链接的访问速度是本地执行速度的7-8倍(降低了85%)。[注]
注意这个速度只是单链接下的极限速度,所以这并不代表MySQL在网络环境下的处理速度(但个人认为极限速度不可能超过2倍),但是我们还是看出,MySQL在网络环境下速度有相当的下降[注]。而使用网络短链接要付出连接和断开连接的成本。
STMT的操作方式(参看STMT的章节)由于不用重新传递分析SQL,在网络环境也表现了出了优于其他方式的性能。
由于测试的数据较少,可能影响到测试的时间准确程度。
对于长链接的网络访问速度有如此的下降,我开始很怀疑,我查询了我原来对Oracle作过的一组入库测试数据,在同样的100M网络环境环境下速度只降低了30%左右。但我重新测试了1000000条的数据,但得到的结果还是如此。(当然也可能是IDC内部的网络过于繁忙)
基于MySQL在网络环境中的表现差强人意,如果硬件条件允许,在作DB服务器设计时,将DB服务器和MySQL放在同一个机器下可能是一个更好的选择。
1.4小结
如何模拟真实的环境一直是我比较头大的问题,不管我如何模拟,好像感觉仍然只能专注到某个方面从而有相对性,而且模拟现实和测试极限性能本身可能就相互矛盾。这些测试数据更多的应该是一种参考,使你了解系统地性能极限和性能瓶颈[注]。如果你能有更好的方法模拟真实环境,请通知我。
通过前面的测试,个人感觉对于类似我测试环境的系统(机器+DB+表),个人感觉真实环境的最高本地处理速度可以接近2500条左右(包括读写),网络操作的最高速度可以接近1500条。