基准测试(benchmark)是MySQL新手和专家都需要掌握的一项基本技能。简单地说,基准测试是针对系统设计的一种压力测试。通常的目标是为了掌握系统的行为。但也有其他原因,如重现某个系统状态,或者是做新硬件的可靠性测试。
2.1 为什么需要基准测试
因为基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法。基准测试可以观察系统在不同压力下的行为,评估系统的容量,掌握哪些是重要的变化,或者观察系统如何处理不同的数据。
基准测试可以完成以下工作,或者更多:
- 验证基于系统的一些假设,确认这些假设是否符合实际情况。
- 重现系统中的某些异常行为,以解决这些异常。
- 测试系统当前的运行情况。
- 模拟比当前系统更高的负载,以找出系统随着压力增加而可能遇到的扩展性瓶颈。
- 规划未来的业务增长。
- 测试应用适应可变环境的能力。
- 证明新采购的设备是否配置正确。
2.2 基准测试的策略
基准测试有两种主要的策略:一是针对整个系统的整体测试,另外是单独测试MySQL。这两种策略也被称为集成式(full-stack)以及单组件式(single-component)基准测试。2.2.1 测试何种指标
在开始执行甚至是在设计基准测试之前,需要先明确测试的目标。测试目标决定了选择什么样的测试工具和技术,以获得精确而有意义的测试结果。
- 使用真实数据的子集而不是全集
- 使用错误的数据分布
- 在多用户场景中,只做单用户的测试
- 在单服务器上测试分布式应用
- 与真实用户行为不匹配
- 忽略了系统预热(warm up)的过程
- 使用默认的服务器配置
- 测试时间太短
2.3.1 设计和规划基准测试
规划基准测试的第一步是提出问题并明确目标。然后决定是采用标准的基准测试,还是设计专用的测试。2.3.2 基准测试应该运行多长时间
基准测试应该运行足够长的时间,这一点很重要。如果需要测试系统在稳定状态时的性能,那么当然需要在稳定状态下测试并观察。而如果系统有大量的数据和内存,要达到稳定状态可能需要非常长的时间2.3.3 获取系统性能和状态
在执行基准测试时,需要尽可能多地收集被测试系统的信息。最好为基准测试建立一个目录,并且每执行一轮测试都创建单独的子目录,将测试结果、配置文件、测试指标、脚本和其他相关说明都保存在其中。
下面是一个收集MySQL测试数据的shell脚本: ```shell!/bin/sh
INTERVAL=5 PREFIX=$INTERVAL-sec-status RUNFILE=/home/benchmarks/running mysql -e ‘SHOW GLOBAL VARIABLES’ >> mysql-variables while test -e $RUNFILE; do file=$(date +%F_%I) sleep=$(date +%s.%N | awk “{print $INTERVAL - (\$1 % $INTERVAL)}”) sleep $sleep ts=”$(date +”TS %s.%N %F %T”)” loadavg=”$(uptime)” echo “$ts $loadavg” >> $PREFIX-${file}-status mysql -e ‘SHOW GLOBAL STATUS’ >> $PREFIX-${file}-status & echo “$ts $loadavg” >> $PREFIX-${file}-innodbstatus mysql -e ‘SHOW ENGINE INNODB STATUS\G’ >> $PREFIX-${file}-innodbstatus & echo “$ts $loadavg” >> $PREFIX-${file}-processlist mysql -e ‘SHOW FULL PROCESSLIST\G’ >> $PREFIX-${file}-processlist & echo $ts done echo Exiting because $RUNFILE does not exist.
<a name="odfQT"></a>## 2.3.4 获得准确的测试结果<a name="z5wTY"></a>## 2.3.5 运行基准测试并分析结果下面是一个非常简单的shell脚本,演示了如何从前面的数据采集脚本采集到的数据中抽取时间维度信息```shell#!/bin/sh# This script converts SHOW GLOBAL STATUS into a tabulated format, one line# per sample in the input, with the metrics divided by the time elapsed# between samples.awk 'BEGIN {printf "#ts date time load QPS";fmt = " %.2f";}/^TS/ { # The timestamp lines begin with TS.ts = substr($2, 1, index($2, ".") - 1);load = NF - 2;diff = ts - prev_ts;prev_ts = ts;printf "\n%s %s %s %s", ts, $3, $4, substr($load, 1, length($load)-1);}/Queries/ {printf fmt, ($2-Queries)/diff;Queries=$2}' "$@"
2.3.6 绘图的重要性
2.4 基准测试工具
2.4.1 集成式测试工具
- ab: 是一个Apache HTTP服务器基准测试工具。它可以测试HTTP服务器每秒最多可以处理多少请求。如果测试的是Web应用服务,这个结果可以转换成整个应用每秒可以满足多少请求。
- http_load: 这个工具概念上和ab类似,也被设计为对Web服务器进行测试,但比ab要更加灵活。
JMeter: JMeter是一个Java应用程序,可以加载其他应用并测试其性能。它虽然是设计用来测试Web应用的,但也可以用于测试其他诸如FTP服务器,或者通过JDBC进行数据库查询测试。
2.4.2 单组件式测试工具
mysqlslap: 可以模拟服务器的负载,并输出计时信息。它包含在MySQL 5.1的发行包中,应该在MySQL 4.1或者更新的版本中都可以使用。测试时可以执行并发连接数,并指定SQL语句(可以在命令行上执行,也可以把SQL语句写入到参数文件中)。如果没有指定SQL语句,mysqlslap会自动生成查询schema的SELECT语句。
- MySQL Benchmark Suite(sql-bench): 在MySQL的发行包中也提供了一款自己的基准测试套件,可以用于在不同数据库服务器上进行比较测试。它是单线程的,主要用于测试服务器执行查询的速度。结果会显示哪种类型的操作在服务器上执行得更快。
- Super Smack: 是一款用于MySQL和PostgreSQL的基准测试工具,可以提供压力测试和负载生成。这是一个复杂而强大的工具,可以模拟多用户访问,可以加载测试数据到数据库,并支持使用随机数据填充测试表。
- Database Test Suite: 是由开源软件开发实验室(OSDL,Open Source Development Labs)设计的,发布在SourceForge网站(http://sourceforge.net/projects/osdldbt/)上,这是一款类似某些工业标准测试的测试工具集,例如由事务处理性能委员会(TPC,Transaction Processing Performance Council)制定的各种标准。
- Percona’s TPCC-MySQL Tool
在评估大压力下MySQL的一些行为时,我们经常会利用这个工具进行测试(简单的测试,一般会采用sysbench替代)。该工具的源代码可以在 https://launchpad.net/perconatools下载,在源码库中有一个简单的文档说明。
- sysbench: sysbench(https://launchpad.net/sysbench)是一款多线程系统压测工具。它可以根据影响数据库服务器性能的各种因素来评估系统的性能。
- MySQL的BENCHMARK()函数: MySQL有一个内置的BENCHMARK()函数,可以测试某些特定操作的执行速度。参数可以是需要执行的次数和表达式。表达式可以是任何的标量表达式,比如返回值是标量的子查询或者函数。
2.5 基准测试案例
2.5.1 http_load
首先创建一个urls.txt文件,输入如下的URL:
http_load最简单的用法,就是循环请求给定的URL列表。测试程序将以最快的速度请求这些URL: ```shell $ http_load -parallel 1 -seconds 10 urls.txt 19 fetches, 1 max parallel, 837929 bytes, in 10.0003 seconds 44101.5 mean bytes/connection 1.89995 fetches/sec, 83790.7 bytes/sec msecs/connect: 41.6647 mean, 56.156 max, 38.21 min msecs/first-response: 320.207 mean, 508.958 max, 179.308 min HTTP response codes:http://www.mysqlperformanceblog.com/http://www.mysqlperformanceblog.com/page/2/http://www.mysqlperformanceblog.com/mysql-patches/http://www.mysqlperformanceblog.com/mysql-performance-presentations/http://www.mysqlperformanceblog.com/2006/09/06/slow-query-log-analyzes-tools/
code 200 - 19
下面是另外一个稍微复杂的测试,还是尽可能快地循环请求给定的URL列表,不过模拟同时有五个并发用户在进行请求:```shell$ http_load -parallel 5 -seconds 10 urls.txt94 fetches, 5 max parallel, 4.75565e+06 bytes, in 10.0005 seconds50592 mean bytes/connection9.39953 fetches/sec, 475541 bytes/secmsecs/connect: 65.1983 mean, 169.991 max, 38.189 minmsecs/first-response: 245.014 mean, 993.059 max, 99.646 minHTTP response codes:code 200 - 94
除了测试最快的速度,也可以根据预估的访问请求率(比如每秒5次)来做压力模拟测试。
$ http_load -rate 5 -seconds 10 urls.txt48 fetches, 4 max parallel, 2.50104e+06 bytes, in 10 seconds52105 mean bytes/connection4.8 fetches/sec, 250104 bytes/secmsecs/connect: 42.5931 mean, 60.462 max, 38.117 minmsecs/first-response: 246.811 mean, 546.203 max, 108.363 minHTTP response codes:code 200 - 48
还可以模拟更大的负载,可以将访问请求率提高到每秒20次请求。请注意,连接和请求响应时间都会随着负载的提高而增加。
$ http_load -rate 20 -seconds 10 urls.txt111 fetches, 89 max parallel, 5.91142e+06 bytes, in 10.0001 seconds53256.1 mean bytes/connection11.0998 fetches/sec, 591134 bytes/secmsecs/connect: 100.384 mean, 211.885 max, 38.214 minmsecs/first-response: 2163.51 mean, 7862.77 max, 933.708 minHTTP response codes:code 200 -- 111
2.5.2 MySQL基准测试套件
MySQL基准测试套件(MySQL Benchmark Suite)由一组基于Perl开发的基准测试工具组成。在MySQL安装目录下的sql-bench子目录中包含了该工具。比如在Debian GNU/Linux系统上,默认的路径是/usr/share/mysql/sql-bench。
如果要运行全部测试,可以使用如下的命令:
$ cd /usr/share/mysql/sql-bench/sql-bench$ ./run-all-tests --server=mysql --user=root --log --fastTest finished. You can find the result in:output/RUN-mysql_fast-Linux_2.4.18_686_smp_i686
除了运行全部测试集外,也可以选择单独执行其中的部分测试项。例如可以选择只执行
insert测试,这会比运行全部测试集所得到的汇总信息给出更多的详细信息:
sql-bench$ ./test-insertTesting server 'MySQL 4.0.13 log' at 2003-05-18 11:02:39Testing the speed of inserting data into 1 table and do some selects on it.The tests are done with a table that has 100000 rows.Generating random keysCreating tablesInserting 100000 rows in orderInserting 100000 rows in reverse orderInserting 100000 rows in random orderTime for insert (300000):42 wallclock secs ( 7.91 usr 5.03 sys + 0.00 cusr 0.00 csys = 12.94 CPU)Testing insert of duplicatesTime for insert_duplicates (100000):16 wallclock secs ( 2.28 usr 1.89 sys + 0.00 cusr 0.00 csys = 4.17 CPU)
2.5.3 sysbench
sysbench可以执行多种类型的基准测试,它不仅设计用来测试数据库的性能,也可以测试运行数据库的服务器的性能。
sysbench的CPU基准测试
最典型的子系统测试就是CPU基准测试。该测试使用64位整数,测试计算素数直到某个最大值所需要的时间。下面的例子将比较两台不同的GNU/Linux服务器上的测试结果。第一台机器的CPU配置如下:
[server1 ~]$ cat /proc/cpuinfo...model name : AMD Opteron(tm) Processor 246stepping : 1cpu MHz : 1992.857cache size : 1024 KB
在这台服务器上运行如下的测试:
[server1 ~]$ sysbench --test=cpu --cpu-max-prime=20000 runsysbench v0.4.8: multithreaded system evaluation benchmark...Test execution summary: total time:121.7404s
第二台服务器配置了不同的CPU:
[server2 ~]$ cat /proc/cpuinfo...model name : Intel(R) Xeon(R) CPU 5130 @ 2.00GHzstepping : 6cpu MHz : 1995.005
测试结果如下:
[server1 ~]$ sysbench --test=cpu --cpu-max-prime=20000 runsysbench v0.4.8: multithreaded system evaluation benchmark...Test execution summary: total time:61.8596s
sysbench的文件I/O基准测试
文件I/O(fileio)基准测试可以测试系统在不同I/O负载下的性能。
首先通过下面的命令创建一个数据集:
$ sysbench --test=fileio --file-total-size=150G prepare
第二步就是运行(run)阶段,针对不同的I/O类型有不同的测试选项:
- seqwr: 顺序写入。
- seqrewr: 顺序重写。
- seqrd: 顺序读取。
- rndrd: 随机读取。
- rndwr: 随机写入。
- rdnrw: 混合随机读/写。
下面的命令运行文件I/O混合随机读/写基准测试:
$ sysbench --test=fileio --file-total-size=150G --file-test-mode=rndrw/ --init-rng=on--max-time=300--max-requests=0 runsysbench v0.4.8: multithreaded system evaluation benchmarkRunning the test with following options:Number of threads: 1Initializing random number generator from timer.Extra file open flags: 0128 files, 1.1719Gb each150Gb total file sizeBlock size 16KbNumber of random requests for random IO: 10000Read/Write ratio for combined random IO test: 1.50Periodic FSYNC enabled, calling fsync() each 100 requests.Calling fsync() at the end of test, Enabled.Using synchronous I/O modeDoing random r/w testThreads started!Time limit exceeded, exiting...Done.Operations performed: 40260 Read, 26840 Write, 85785 Other = 152885 TotalRead 629.06Mb Written 419.38Mb Total transferred 1.0239Gb (3.4948Mb/sec)223.67 Requests/sec executedTest execution summary:total time: 300.0004stotal number of events: 67100total time taken by event execution: 254.4601per-request statistics:min: 0.0000savg: 0.0038smax: 0.5628sapprox. 95 percentile: 0.0099sThreads fairness:events (avg/stddev): 67100.0000/0.00execution time (avg/stddev): 254.4601/0.00
测试完成后,运行清除(cleanup)操作删除第一步生成的测试文件:
$ sysbench --test=fileio --file-total-size=150G cleanup
sysbench的OLTP基准测试
OLTP基准测试模拟了一个简单的事务处理系统的工作负载。下面的例子使用的是一张超过百万行记录的表,第一步是先生成这张表:
$ sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test/ --mysql-user=root preparesysbench v0.4.8: multithreaded system evaluation benchmarkNo DB drivers specified, using mysqlCreating table 'sbtest'...Creating 1000000 records in table 'sbtest'...
接下来可以运行测试,这个例子采用了8个并发线程,只读模式,测试时长60秒:
$ sysbench --test=oltp --oltp-table-size=1000000 --mysql-db=test --mysql-user=root/ --max-time=60 --oltp-read-only=on --max-requests=0 --num-threads=8 runsysbench v0.4.8: multithreaded system evaluation benchmarkNo DB drivers specified, using mysqlWARNING: Preparing of "BEGIN" is unsupported, using emulation(last message repeated 7 times)Running the test with following options:Number of threads: 8Doing OLTP test.Running mixed OLTP testDoing read-only testUsing Special distribution (12 iterations, 1 pct of values are returned in 75 pctcases)Using "BEGIN" for starting transactionsUsing auto_inc on the id columnThreads started!Time limit exceeded, exiting...(last message repeated 7 times)Done.OLTP test statistics:queries performed:read: 179606write: 0other: 25658total: 205264transactions: 12829 (213.07 per sec.)deadlocks: 0 (0.00 per sec.)read/write requests: 179606 (2982.92 per sec.)other operations: 25658 (426.13 per sec.)Test execution summary:total time: 60.2114stotal number of events: 12829total time taken by event execution: 480.2086per-request statistics:min: 0.0030savg: 0.0374smax: 1.9106sapprox. 95 percentile: 0.1163sThreads fairness:events (avg/stddev): 1603.6250/70.66execution time (avg/stddev): 60.0261/0.06
2.5.4 数据库测试套件中的dbt2TPC-C测试
数据库测试套件(Database Test Suite)中的dbt2是一款免费的TPC-C测试工具。TPC-C是TPC组织发布的一个测试规范,用于模拟测试复杂的在线事务处理系统(OLTP)。它的测试结果包括每分钟事务数(tpmC),以及每事务的成本(Price/tpmC)。
准备测试数据。下面的命令会在指定的目录创建用于10个仓库的数据。每个仓库使用大约700MB磁盘空间,测试所需要的总的磁盘空间和仓库的数量成正比。因此,可以通过-w参数来调整仓库的个数以生成合适大小的数据集。 ```shell
src/datagen -w 10 -d /mnt/data/dbt2-w10
warehouses = 10 districts = 10 customers = 3000 items = 100000 orders = 3000 stock = 100000 new_orders = 900
Output directory of data files: /mnt/data/dbt2-w10
Generating data files for 10 warehouse(s)… Generating item table data… Finished item table data… Generating warehouse table data… Finished warehouse table data… Generating stock table data…
2. 加载数据到MySQL数据库。下面的命令创建一个名为dbt2w10的数据库,并且将上一步生成的测试数据加载到数据库中(-d参数指定数据库,-f参数指定测试数据所在的目录)。```shell# scripts/mysql/mysql_load_db.sh -d dbt2w10 -f /mnt/data/dbt2-w10/-s /var/lib/mysql/mysql.sock
- 运行测试。

