重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
当我们对数据库进行优化后,只有进行测量系统性能才能知道优化是否有效,这种测量的方式就是基准测试。基准测试的定义如下:
成都创新互联公司2013年成立,先为秀屿等服务建站,秀屿等地企业,进行企业商务咨询服务。为秀屿企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
基准测试是一种测量和评估软件性能指标的活动用于建立某个时刻的性能基准,以便当系统发生软/硬件变化时,重新进行基准测试以评估变化对性能的影响
我们可以这样认为:
基准测试是针对系统设置的一种压力测试,可以用来观察系统在不同压力下的行为。评估系统的容量,观察系统如何处理不同的数据。
但是基于测试不等同于压力测试:
对MySQL进行基准测试的目的:
通常来说,基准测试有两种方式:
MySQL基准测试的常见指标:
基准测试中容易忽略的问题:
基准测试的步骤:
基准测试数据的收集脚本:
#!/bin/bash
# 脚本的运行间隔
INTERVAL=5
# 创建数据文件的存储目录
STORE_DIR=/home/mysql/benchmarks
mkdir -p $STORE_DIR
# 将收集的数据存储到哪个目录下,以及文件前缀
PREFIX=$STORE_DIR/$INTERVAL-sec-status
# 设置脚本的运行标识
RUNFILE=$STORE_DIR/running
touch $RUNFILE && echo "1" > $RUNFILE
# mysql的用户名和密码
USER=root
PWD=123456
# mysql命令所在的路径
MYSQL="/usr/local/mysql/bin/mysql -u$USER -p$PWD"
# 记录当前mysql的全局变量
$MYSQL -e "show global variables" >> mysql-variables
# 运行标识文件存在就会一直循环
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的全局变量信息
$MYSQL -e "show global status" >> $PREFIX-${file}-status &
echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus
# 记录当前 innodb 的状态信息
$MYSQL -e "show engine innodb status" >> $PREFIX-${file}-innodbstatus &
echo "$ts $loadavg" >> $PREFIX-${file}-processlist
# 记录当前mysql全部连接信息列表
$MYSQL -e "show full processlist\G" >> $PREFIX-${file}-processlist &
echo $ts
done
echo Exiting because $RUNFILE does not exists
测试数据分析脚本:
#!/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",ts,$3,$4,substr($load,1,length($load)-1);
prev_ts=ts;
}
/Queries/{
printf fmt,($2-Queries)/diff;
Queries=$2
}
' "$@"
### 使用示例 ###
# sh ./analyze.sh ${测试数据文件路径}
# 如:sh ./analyze.sh /home/mysql/benchmarks/5-sec-status-2020-01-11_04-status
一般来说,我们都不会自己去编写基准测试的脚本,因为都有现成的工具。例如,mysql 5.1以上版本都自带了mysqlslap这个基准测试工具。由于是自带的也无需进行单独的安装,该工具位于mysql的bin
目录下。
功能简介:
常用参数说明:
参数 | 说明 |
---|---|
--concurrency |
并发数量,即模拟的客户端数量,可以指定多个,使用逗号分隔 |
--iterations |
指定测试的运行次数 |
--auto-generate-sql |
使用系统自动生成的SQL脚本来进行测试 |
--auto-generate-sql-add-autoincrement |
在自动生成的表中增加自增ID |
--auto-generate-sql-load-type |
指定测试中使用的查询类型(取值:read, write, update, mixed),默认mixed |
--auto-generate-sql-write-number |
指定初始化数据时所生成的数据量 |
--engine |
要测试表的存储引擎,允许指定多个,使用逗号分隔 |
--no-drop |
指定不清理测试数据 |
--number-of-queries |
指定每一个连接执行的查询次数 |
--debug-info |
指定输出额外的内存及CPU统计信息 |
--number-char-cols |
指定测试表中包含的int 类型的数量 |
--number-int-cols |
指定测试表中包含的varchar 类型的数量 |
--create-schema |
指定用于执行测试的数据库的名称 |
--query |
用于指定自定义的SQL脚本 |
--only-print |
指定该参数时,不会运行测试脚本,而是把生成的脚本打印出来 |
使用示例:
[root@localhost ~]# mysqlslap -uroot -p123456 --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=test
运行该测试后,截取的部分输出片段如下:
Benchmark
# 运行的是myisam引擎的测试
Running for engine myisam
# 运行所有查询的平均秒数
Average number of seconds to run all queries: 0.020 seconds
# 运行所有查询的最小秒数
Minimum number of seconds to run all queries: 0.018 seconds
# 运行所有查询的最大秒数
Maximum number of seconds to run all queries: 0.022 seconds
# 运行查询的客户端数
Number of clients running queries: 1
# 每个客户端的平均查询数
Average number of queries per client: 10
Benchmark
Running for engine innodb
Average number of seconds to run all queries: 0.049 seconds
Minimum number of seconds to run all queries: 0.042 seconds
Maximum number of seconds to run all queries: 0.059 seconds
Number of clients running queries: 1
Average number of queries per client: 10
除了 mysqlslap 这个mysql自带的基准测试工具之外,还有一个常用的工具就是 sysbench。sysbench的功能比mysqlslap更多一些,能测试的点也更全面一些。sysbench除了可以测试MySQL外,还能测试系统的CPU、IO、内存等方面。
sysbench的GitHub仓库地址及源码安装文档如下:
一般系统中不会自带sysbench工具,需要我们自行安装,我这里采用源码编译安装的方式进行安装。首先到如下地址复制源码包的下载链接:
然后到Linux上使用wget
命令进行下载:
[root@txy-server ~]# cd /usr/local/src
[root@txy-server /usr/local/src]# wget https://github.com/akopytov/sysbench/archive/1.0.19.tar.gz
安装编译sysbench时所依赖的一些库:
[root@txy-server /usr/local/src]# yum -y install make automake libtool pkgconfig libaio-devel mariadb-devel openssl-devel
接着将下载好的源码包进行解压缩,并进入到解压后的目录:
[root@txy-server /usr/local/src]# tar -zxvf 1.0.19.tar.gz
[root@txy-server /usr/local/src]# cd sysbench-1.0.19/
最后参考以下步骤完成编译安装:
[root@txy-server /usr/local/src/sysbench-1.0.19]# ./autogen.sh
[root@txy-server /usr/local/src/sysbench-1.0.19]# ./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib
[root@txy-server /usr/local/src/sysbench-1.0.19]# make && make install
等待完成编译安装后,测试是否安装成功。我这里报了个找不到库文件的错误:
[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench: error while loading shared libraries: libmysqlclient.so.21: cannot open shared object file: No such file or directory
解决方式是建立一个该文件的软连接到/usr/lib64/
目录下:
[root@txy-server /usr/local/src/sysbench-1.0.19]# ln -s /usr/local/mysql/lib/libmysqlclient.so.21 /usr/lib64/
再次测试,执行成功:
[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench 1.0.19
sysbench的命令格式如下:
sysbench [options]... [testname] [command]
1、options,是指定测试参数,以下是使用sysbench测试MySQL时常用的参数:
--mysql-db
:用于指定基准测试的数据库名称,该数据库必须是已存在的--mysql_storage_engine
:指定测试的MySQL存储引擎--tables
:执行测试的表的数量--table_size
:指定每个表中的数据量--threads
:指定测试的并发线程数量--max-time
:指定最大测试时间,单位为秒--report-interval
:指定间隔多长时间就输出一次统计信息,单位为秒--mysql-socket
:指定mysql的.sock
文件路径,用于连接mysql--mysql-user
:指定用于测试时连接mysql的用户--mysql-password
:指定mysql用户的密码2、testname,是指定内置的测试类型或测试脚本。内置的测试类型有如下取值:
fileio
:测试文件系统I/O性能cpu
:测试cpu性能memory
:测试内存性能threads
:测试线程性能mutex
:测试互斥锁性能sysbench [testname] help
,可以查看各个测试类型所支持的参数除内置测试类型以外的测试,就需要指定测试脚本。sysbench的测试脚本需要使用lua语言编写,可以根据实际需求编写自已的测试脚本,也可以使用sysbench自带的测试脚本。sysbench自带的lua脚本如下:
[root@txy-server ~]# ls /usr/local/share/sysbench
bulk_insert.lua # 用于测试大量的insert操作性能
oltp_common.lua # 公共文件,给其他脚本引用的,不可直接使用
oltp_delete.lua # 用于测试oltp下的delete操作性能
oltp_insert.lua # 用于测试oltp下的insert操作性能
oltp_point_select.lua # 用于测试oltp下的定点查询性能,例如根据主键查询
oltp_read_only.lua # 用于测试oltp下的只读性能
oltp_read_write.lua # 用于测试oltp下的读写性能
oltp_update_index.lua # 用于测试更新索引字段的性能
oltp_update_non_index.lua # 用于测试更新无索引字段操作的性能
oltp_write_only.lua # 用于测试oltp下的写操作性能
select_random_points.lua # 用于测试随机定点查询的性能
select_random_ranges.lua # 用于测试随机范围读取的性能
...
3、command,则是指定一些测试操作,例如运行测试、清除数据或准备数据等:
prepare
:用于测试开始前准备测试数据run
:用于测试数据准备完成后,执行测试cleanup
:用于测试执行完成后清理测试数据以下命令可以让cpu找出10000以内的素数,并统计计算所需耗时,以此得知cpu的性能。需要注意的是,这种方式测试的是单核心性能,而非多核性能:
[root@txy-server ~]# sysbench --cpu-max-prime=10000 cpu run
测试结果如下:
# CPU速度
CPU speed:
# 每秒事件数
events per second: 1039.79
General statistics:
# 计算出所有素数的总耗时
total time: 10.0005s
# 总的事件数
total number of events: 10400
Latency (ms):
# 计算出一个素数的最低耗时
min: 0.94
# 平均计算出一个素数的耗时
avg: 0.96
# 计算出一个素数的最长耗时
max: 9.43
# 95%情况是1.01毫秒计算出一个素数
95th percentile: 1.01
# 合计耗时
sum: 9994.05
# 线程公平性
Threads fairness:
events (avg/stddev): 10400.0000/0.00
execution time (avg/stddev): 9.9941/0.00
测试I/O性能需要先准备测试数据,测试数据的大小需要大于物理内存。命令如下:
# 该命令会生成127个测试文件,这些文件合计4G大小
[root@txy-server ~]# sysbench --file-total-size=4G fileio prepare
...
Creating file test_file.125
Creating file test_file.126
Creating file test_file.127
4294967296 bytes written in 39.00 seconds (105.04 MiB/sec).
[root@txy-server ~]#
数据准备好后,执行测试:
[root@txy-server ~]# sysbench --threads=8 --file-total-size=4G --file-test-mode=rndrw --report-interval=1 fileio run
参数说明:
--threads=8
:设置并发线程数为8--file-test-mode=rndrw
:指定文件测试模式为随机读写,即测试磁盘I/O的随机读写性能--report-interval=1
:指定每秒输出一次统计信息测试结果如下:
File operations:
reads/s: 2089.75
writes/s: 1392.67
fsyncs/s: 4553.64
Throughput:
# 每秒读取
read, MiB/s: 32.65
#
written, MiB/s: 21.76
General statistics:
total time: 10.0778s
total number of events: 79973
Latency (ms):
min: 0.00
avg: 1.00
max: 58.42
95th percentile: 3.13
sum: 79895.62
Threads fairness:
events (avg/stddev): 9996.6250/43.23
execution time (avg/stddev): 9.9870/0.01
最后执行cleanup
操作,清除测试数据:
[root@txy-server ~]# sysbench --file-total-size=4G fileio cleanup
由于sysbench内置的测试类型没有MySQL,所以在使用sysbench测试MySQL时,testname需要指定为测试脚本的路径。sysbench自带了一些MySQL的测试脚本,所以无特殊需求的情况下,我们也无需自己去编写测试脚本。接下来,进行一个简单的演示,看看如何使用测试脚本来测试MySQL的性能。
首先也是需要准备数据,命令如下:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua prepare
执行测试:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua run
测试结果如下:
SQL statistics:
queries performed:
# 读取操作的总数
read: 10444
# 写操作的总数
write: 2984
# 其他操作的总数,例如commit等
other: 1492
# 总共执行的操作数量
total: 14920
# 每秒执行的事务数,即TPS,这里为每秒74.48次
transactions: 746 (74.48 per sec.)
# 每秒查询的数量,即QPS,这里为每秒1489.53次
queries: 14920 (1489.53 per sec.)
# 忽略的错误次数
ignored errors: 0 (0.00 per sec.)
# 重连次数
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 10.0150s
total number of events: 746
Latency (ms):
min: 8.86
avg: 13.42
max: 99.97
95th percentile: 20.00
sum: 10009.79
Threads fairness:
events (avg/stddev): 746.0000/0.00
execution time (avg/stddev): 10.0098/0.00
同样,最后需要清理测试数据:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua cleanup
如果想要知道测试脚本具体支持哪些参数,其查看方式和内置测试类型是一样的,只不过把测试类型的名称换成了脚本而已:
[root@txy-server ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua help