基准测试:是一种测量和评估软件性能指标的活动,用于建立某个时刻的性能基准,以便当系统发生软硬件变化时重新进行基准测试以评估变化对性能的影响。基准测试是针对系统设置的一种压力测试,可以观察系统在不同压力下的行为,评估系统的容量,观察系统如何处理不同的数据。
但是基准测试和通常的压力测试还是有区别的:
(1)基准测试:直接、简单、使各个结果之间易于比较,测试数据基本上是由测试工具生成的,只能用于评估服务器的处理能力。
(2)压力测试:对真实的业务数据进行测试,获得真实系统所能承受的压力。因此基准测试只是一种简化了的压力测试。基准测试给系统带来的压力通常只能用来测量系统的一些性能,忽略了对系统的逻辑压力测试。
例如对一个网站进行压力测试,需要针对不同的主题进行,购物车流程的压力测试就需要按照购物流程的业务逻辑来设计测试要包含哪些业务流程,所使用的数据和查询也是在整个购物流程中需要真实用到的;而基准测试可能不关心业务逻辑,所使用的查询和业务环境没关系。例如对MySQL进行基本测试,可能就不会关心在MySQL上运行的系统的逻辑是什么,可以使用一个简单的查询通过多线程并发来衡量调优后的结果是否有效。
基准测试有两个主要的策略:一是针对整个系统的整体测试,另外是单独测试MySQL。这两种策略也被称为集成式(full-stack)以及但组件式(single-component)基准测试。
(1)对整个系统进行基准测试:一般从系统入口进行测试(如网站Web前端,手机APP前端)。
优点:够测试整个系统,包括web服务器缓存、数据库等;能够反映出系统中各个组件接口间的性能问题体现真实性能状况
缺点:测试设计复杂,消耗的时间长
(2)单独对MySQL进行基准测试
优点:测试设计简单,所需耗费时间短
缺点:无法全面了解整个系统的性能基线
QPS:Queries Per Second,即每秒查询率,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
TPS: Transactions Per Second,即事务数/秒,这个完整的事务包括了用户请求服务器,服务器内部处理,服务器返回信息给用户三个过程。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
这两个指标常用来衡量系统的吞吐量(单位时间内的事务处理数)。
(1)计划和设计基准测试
基准测试的设计要尽可能简单,在这一步要明确基准测试的方式是哪一种,是对整个系统进行基准测试还是某个组件,如MySQL进行基准测试。还需要确定使用什么样的数据,如果希望基准测试能够反映出系统的实际情况,那么就最好使用生产中的实际数据和实际中的SQL来完成基准测试,如果要使用这种方式进行基准测试就需要注意最好使用生产环境中数据库的备份或者一定时间内实际产生的的sql日志来运行多线程的回放完成基准测试,这种方式相对比较负载,准备数据的时间比较多页比较复杂。如果只想知道某个参数的调整对数据库的影响的话就可以使用专门的测试工具来生成所需要的数据和SQL,以此来完成基准测试,这种方式更假简单。在这一步中还需要确定基准测试所要进行的时间和次数,通过多次测试得出的平均统计结果来反映系统的真实性能。
(2)准备基准测试及数据收集脚本
一般需要收集CPU使用率、IO、网络流量、状态与计数器信息等。
# 下面是一个简单的收集MySQL测试数据的shell脚本
INTERVAL=5 #运行间隔,每隔多少时间收集一下状态信息
PREFIX=/home/imooc/benchmarks/$INTERVAL-sec-status#定义了状态信息的存储位置
RUNFILE=/home/imooc/benchmarks/running#指定了运行标识,如果存在标识,证明脚本在运行,想停止脚本,就删除标识文件的方式来停止脚本
echo "1">$RUNFILE #标识文件
MYSQL=/usr/local/mysql/bin/mysql #mysql命令所在的位置
$MYSQL -e "show global variables" >>mysql-variables#记录了进行测试的当前mysql的一些设置信息
while test -e $RUNFILE; #循环体开始
do
file=$(date +%F_%I) #定义了脚本运行时间
sleep=$(date +%s.$N | awk '{print 5 - ($1 % 5)}') #每隔多久运行一次脚本
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 & #mysql的全局的状态信息
echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus #记录在文件里
$MYSQL -e "show engine innodb status" >> $PREFIX-${file}-innodbstatus & #收集innodb的状态信息
echo "$ts $loadavg" >> $PREFIX-${file}-processlist
$MYSQL -e "show full processlist\G" >> $PREFIX-${file}-processlist & #收集mysql线程的情况
echo $ts
done
echo Exiting because $RUNFILE does not exists
(3)运行记基准测试
(4)保存及分析基准测试结果
最好以图形的方法来展示测试结果。
# 下面是保存分析结果的脚本示例
#!/bin/bash
awk '
BEGIN {
printf "#ts date time load QPS";
fmt=" %.2f";
}
/^TS/ {
ts=substr($2,1,index($2,".")-1);
load=NF-2;
diff=ts-prev_ts;
printf "\n%s %s %s %s %s",ts,$3,$4,substr($load,1,length($load)-1);
prev_ts=ts;
}
/Queries/{
print fmt,($2-Queries)/diff;
Queries=$2
}
' "$@"
基准测试中容易忽略的问题:
mysqlslap是mysql自带的一款基准测试工具,随MySQL一起安装。可以模拟服务器负载,并输出相关统计信息可以指定也可以自动生成查询语句。
常用参数说明:
--auto-generate-sql
用于指定由系统自动生成脚本进行测试还是使用自己的数据和sql进行测试。如果指定代表用系统自己生成的SQL脚本来测试。
--auto-generate-sql-add-autoincrement
指定了在自动生成表中是否要增加自增id列,如果是对innodb引擎进行测试,这个参数很重要,因为innodb
的主键是聚集索引,最好使用自增id来作为innodb表的主键。
--auto-generate-sql-load-type
它指定了测试中使用的查询类型,默认使用混合测试类型,代表同时包括了读写查询删除更新等混合sql语句进行测试
--auto-generate-sql-wite-number 指定了mysqlslap可以自动生成测试数据的数据量是多少,一般情况下这个参数初始化是100行数据。
--concurrency
代表并发数量,多个可以用逗号隔开,例如:concurrency=10,50,100, 并发连接线程数分别是10、50、100个并发。
--engines
代表要测试的引擎,可以有多个,用分隔符隔开。mysql会先进行一种测试,比如myisam,测试完后再进行innodb进行测试
--no-drop
指定不清理测试数据,在默认情况下,mysql对数据完成一次测试之后会对自动生成的数据进行清理
--iterations
代表要运行这些测试多少次。如果要得出正确结果,最好执行多次,多次测试得出百分比,得出相对稳定的测试结果,同样mysqlslap每测试一次就会重新生成测试数据,所以如果我们制定此参数就不能指定no-drop参数,是相互冲突的
--number-of-queries
指定每个线程执行查询的次数,代表总共要运行多少次查询。每个客户端运行的查询数量可以用查询总数/并发数来计
算。
--debug-info
指定此参数,代表要额外输出CPU以及内存的相关信息。
--number-int-cols
指定创建测试表的 int 型字段数量
--number-char-cols
指定创建测试表的 char 型字段数量。
--create-schema
指定测试的数据库的名字,MySQL中schema也就是database。
--query
使用自定义脚本执行测试,例如可以调用自定义的一个存储过程或者sql语句来执行测试。
--only-print
并不运行测试脚本,而是把生成的脚本打印出来
下面通过这个测试工具对MyISAM和Innodb存储引擎进行简单的测试:
直接在centos7的命令行执行命令:
mysqlslap -u用户名 -p密码 --concurrency=1,50,100,200 --iterations=3
--number-int-cols=5 --number-char-cols=5 --auto-generate-sql
--auto-generate-sql-add-autoincrement --engine=myisam,innodb
--number-of-queries=10 --create-schema=newtest
可以看出在线程比较少的情况下myisam的性能优于innodb存储引擎。
sysbench更为通用,同样是一款多线程的基准测试工具,可以对影响数据库服务器性能的各种因素进行测试,并评估性能的表现,可以对IO、CPU、内存以及数据库服务器等等进行测试,同时支持脚本语言,可以对各种场景进行测试,使用起来非常灵活,是一款非常全面的测试工具,也是最常用的基准测试工具,同时测试方式更接近于InnoDB的数据方式,可以很好地对mysql硬件进行测试。(mysqlslap不能测试CPU和IO的性能)
安装步骤可以参考博客:centos7安装sysbench
--mysql-db //用户指定执行基准测试的数据库名
--mysql-table-engine //用于指定所使用的存储引擎
--oltp-tables-count //执行测试的表的数量
--oltp-table-size //指定每个表中的数据行数
--num-threads //指定测试的并发线程数量
--max-time //指定最大的测试时间
--report-interval //指定间隔多长时间输出一次统计信息
--mysql-user //指定执行测试的Mysql用户
--mysql-password //指定执行测试的Mysql密码
prepare //用于准备测试数据
run //用于实际进行测试
cleanup //用于清理测试数据
(1)对CPU进行基准测试
sysbench --test=cpu --cpu-max-prime=10000 run//CPU进行的最大计算整数值是10000
结果:
(2)磁盘I/O性能进行测试
sysbench可以测试不同I/O下的性能,可以通过测试系统来调整I/O子系统,sysbench的I/O基准测试是模拟了很多innodb的I/O特性,因此使用sysbench进行测试的话更多是体现innodb的性能特点。再进行测试之前要生成一些数据,需要注意的是生成的数据文件一定要比内存大,否则就会直结缓存大部分数据,无法体现I/O运行的工作负载。
查看内存大小 free -m
生成测试文件 sysbench --test=fileio --file-total-size=1G prepare
//使用8个线程对刚刚生成的数据进行随机读取,并每隔一秒统计一次结果
sysbench --test=fileio --num-threads=8 --file-total-size=1G --file-test-mode=rndrw --report-interval=1 run
(3)模拟oltp测试
第一步生成测试数据
#不同版本的语句不同,以下是基于0.10,需要进入sysbench目录/src/lua路径下执行
sysbench oltp_read_write.lua --mysql-host=127.0.0.1 --mysql-port=3306
--mysql-db=test --mysql-user=root --mysql-password=123456
--table-size=10000 --tables=10 prepare
第二步开始测试
启动收集系统状态的脚本,即在3.1中保存分析结果的示例脚本
执行基准测试
sysbench oltp_read_write.lua --mysql-host=127.0.0.1
--mysql-port=3306 --mysql-db=test --mysql-user=root
--mysql-password=123456 --table-size=10000 --tables=10 run
(3)删除测试数据
sysbench oltp_read_write.lua --mysql-host=127.0.0.1 --mysql-port=3306
--mysql-db=test --mysql-user=root --mysql-password=123456
--table-size=10000 --tables=10 cleanup
可以参考博客:sysbench 测试mysql数据库