2. MySQL基准测试

2020-04-27  本文已影响0人  darcyaf

2.1 为什么需要基准测试

基准测试是唯一方便有效的,可以学习系统在一定的工作负载下会发生什么的办法。
基准测试可以完成以下工作:

2.2 基准测试的策略

一种是针对整个系统的测试,另外一种是单独测试MySQL。这两种分别称为集成式测试以及单组件式测试。
针对整个系统测试的主要原因如下:

基于MySQL的单组件测试的原因如下:

如果可能最好基于生产环境的数据快照来做,能模拟真实的环境。但是基于真实数据的测试过于复杂和耗时,通常是通过模拟大量的数据和压力在做测试。

2.2.1 测试何种指标

测试的指标通常如下:

2.3 基准测试方法

常见错误测试:

如果采用标准的基准测试,应该确认是否采用了合适的测试方案。如,不要使用TPC-H测试电子商务系统,TPC-H是即席查询和决策执行型的基准测试,不适合用在实时查询的OLTP上。

  1. 最好的办法是选择一个有代表性的时间段,比如高峰期的一个小时,记录生产系统上的所有查询。
  2. 如果是集成式基准测试,可以记录Web服务器上的HTTP请求,也可以打开MySQL的查询日志(Query Log)。如果要重演这些查询,就要确保创建多线程在并行执行,并且对日志中的每个连接都应该创建单独的线程。

即使不需要创建专用的基准测试,最好也详细写下测试规划。毕竟测试可能会多次运行。测试规划应记录测试数据,系统配置的步骤,如何测量和分析结果,以及预热的方案等。

2.3.2 基准测试应该运行多长时间

如果需要测试系统在稳定状态下的性能,那么当然需要在稳定状态下测试观察。
而如果有大量的数据和内存,要达到稳定状态需要非常长的时间。大部分系统都有一些应付突发情况的余量,能够吸收性能尖峰,将一些工作延迟到高峰期之后执行。当对机器持续加压后,余量会被耗尽。系统的短期尖峰也就无妨维持原来的高性能。

一个常见的错误是只进行一系列短期的测试,比如每次60秒。如果没有时间去做基准测试,那么有时候可以去相信别人的测试结果,总比自己得出了错误的结论来的好。

2.3.3 获取系统性能和状态

在做基准测试时,需要尽可能多的收集被测试系统的信息,最好为每轮测试建立一个单独的子目录,将测试结果,配置文件,测试指标,脚本和相关说明等都保存在其中。需要记录的数据包括系统状态和性能指标, 诸如cpu使用率,磁盘I/O, 网络流量统计,Show global status 计数器等等。
以下脚本可以简单的收集mysql的状态。

#!/bin/sh
PASSWORD=youpassword
USER=root
INTERVAL=5
PREFIX=$INTERVAL-sec-status
RUNFILE=~/Development/mysql/benchmarks/running
mysql -u $USER --password=$PASSWORD -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="$(/usr/bin/uptime)"
    echo "$ts $loadavg" >> $PREFIX-${file}-status
    mysql -u $USER --password=$PASSWORD -e 'show global status' >> $PREFIX-${file}-status &
    echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus
    mysql -u $USER --password=$PASSWORD -e 'show engine innodb status\G' >> $PREFIX-${file}-innodbstatus &
    echo "$ts, $loadavg" >> $PREFIX-${file}-processlist
    mysql -u $USER --password=$PASSWORD -e 'show full processlist\G' >> $PREFIX-${file}-processlist &
    echo $ts
done

echo Exiting because $RUNFILE does not exist.

以下脚本是分析status文件的数据

#!/bin/bash

# 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-Quries)/diff;
        Queries=$2
    }
    ' "$@"

2.3.6 绘图

有的问题没法通过平均值看出来,这时候可以用画图的方式可以更容易查看

2.4 基准测试工具

2.4.1 集成式测试工具

2.4.2 单组件式测试工具

MariaDB [test]> set @input:='hello world';
Query OK, 0 rows affected (0.000 sec)

MariaDB [test]> select benchmark(100000,md5(@input));
+-------------------------------+
| benchmark(100000,md5(@input)) |
+-------------------------------+
|                             0 |
+-------------------------------+
1 row in set (0.017 sec)

MariaDB [test]> select benchmark(100000,sha1(@input));
+--------------------------------+
| benchmark(100000,sha1(@input)) |
+--------------------------------+
|                              0 |
+--------------------------------+
1 row in set (0.021 sec)

可以看出md5比sha1快上一些
执行后的返回值永远是0,可以通过客户端返回时间来判断执行的时间。
这个函数只是返回服务器执行表达式的时间,而不会涉及分析和优化的开销。
而且表达式必须要这样包含用户定义的变量,否则多次执行同样的表达式会由于命中缓存而影响结果。

2.5 基准测试案例

http_load

5个并发执行10s
http_load -parallel 5 -seconds 10 urls.txt
结果做了简单的统计:
多少连接数,每次连接的耗时等等

(base) ➜  tmp http_load -rate 5 -seconds 10 urls.txt
49 fetches, 1 max parallel, 69776 bytes, in 10.0133 seconds
1424 mean bytes/connection
4.89351 fetches/sec, 6968.36 bytes/sec
msecs/connect: 32.4432 mean, 33.151 max, 27.304 min
msecs/first-response: 19.009 mean, 22.923 max, 12.259 min
HTTP response codes:
  code 200 -- 49

也可以指定 -rate N 执行每秒N个请求。
http_load -rate 5 -seconds 10 urls.txt

2.5.3 sysbench

sysbench 的CPU基准测试

这个测试使用64位整数,测试计算素数直到某个最大值所需要的时间。

sysbench --test=cpu --cpu-max-prime=20000 run

WARNING: the --test option is deprecated. You can pass a script name or path on the command line without any options.
sysbench 1.0.15 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Prime numbers limit: 20000

Initializing worker threads...

Threads started!

CPU speed:
    events per second:   553.57

General statistics:
    total time:                          10.0012s
    total number of events:              5537

Latency (ms):
         min:                                    1.77
         avg:                                    1.81
         max:                                    2.94
         95th percentile:                        1.89
         sum:                                 9999.88

Threads fairness:
    events (avg/stddev):           5537.0000/0.00
    execution time (avg/stddev):   9.9999/0.00

sysbench的文件I/O基准测试

文件I/O(fileio) 基准测试可以测试系统在不同I/O负载下的性能。这对于比较不同的磁盘驱动器,不同的RAID卡,不同的RAID模式,都很有帮助。
可以根据测试结果来调整I/O子系统。
测试的第一步是准备阶段,生成测试用到的数据文件,生成的数据文件至少要比内存大。如果生成的数据能完全放入内存中,则操作系统缓存大部分的数据,导致测试结果无法体现I/O密集型的工作负载。
首先通过下面的命令创建一个数据集:
sysbench --test=fileio --file-total-size=150G prepare
第二部分就是运行阶段
测试10G文件的顺序写和随机写的能力
sysbench fileio --file-total-size=10G --file-test-mode=rndrw --time=300 run
分别展示了文件操作数,吞吐量,统计,延迟等等信息,

sysbench 1.0.15 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Extra file open flags: (none)
128 files, 80MiB each
10GiB total file size
Block size 16KiB
Number of IO requests: 0
Read/Write ratio for combined random IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random write test
Initializing worker threads...

Threads started!


File operations:
    reads/s:                      0.00
    writes/s:                     2190.83
    fsyncs/s:                     2804.36

Throughput:
    read, MiB/s:                  0.00
    written, MiB/s:               34.23

General statistics:
    total time:                          10.0359s
    total number of events:              50033

Latency (ms):
         min:                                    0.00
         avg:                                    0.20
         max:                                    5.88
         95th percentile:                        0.67
         sum:                                 9918.60

Threads fairness:
    events (avg/stddev):           50033.0000/0.00
    execution time (avg/stddev):   9.9186/0.00

sysbench fileio --file-total-size=10G --file-test-mode=seqwr run

sysbench 1.0.15 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 1
Initializing random number generator from current time


Extra file open flags: (none)
128 files, 80MiB each
10GiB total file size
Block size 16KiB
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing sequential write (creation) test
Initializing worker threads...

Threads started!


File operations:
    reads/s:                      0.00
    writes/s:                     9191.44
    fsyncs/s:                     11776.73

Throughput:
    read, MiB/s:                  0.00
    written, MiB/s:               143.62

General statistics:
    total time:                          10.0080s
    total number of events:              209749

Latency (ms):
         min:                                    0.01
         avg:                                    0.05
         max:                                    7.18
         95th percentile:                        0.08
         sum:                                 9932.04

Threads fairness:
    events (avg/stddev):           209749.0000/0.00
    execution time (avg/stddev):   9.9320/0.00

可以看出,顺序读写的速度大概是随机读写的5倍左右。
测试完毕后通过sysbench fileio cleanup清除测试文件。

sysbench的OLTP基准测试

下面是模拟一张超过百万行记录的事务处理系统的工作负载。

sysbench /usr/share/sysbench/oltp_insert.lua --db-driver=mysql --threads=8 --mysql-user=root --mysql-password=abigail prepare

执行run命令
返回中包含以下信息

(base) ➜  tmp sysbench /usr/share/sysbench/oltp_insert.lua --table-size=1000000 --db-driver=mysql --threads=8 --mysql-user=root --mysql-password=abigail run
sysbench 1.0.15 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 8
Initializing random number generator from current time


Initializing worker threads...

Threads started!

SQL statistics:
    queries performed:
        read:                            0
        write:                           60621
        other:                           0
        total:                           60621
    transactions:                        60621  (6057.43 per sec.)
    queries:                             60621  (6057.43 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          10.0024s
    total number of events:              60621

Latency (ms):
         min:                                    0.50
         avg:                                    1.32
         max:                                   11.65
         95th percentile:                        2.03
         sum:                                79719.63

Threads fairness:
    events (avg/stddev):           7577.6250/18.39
    execution time (avg/stddev):   9.9650/0.00

sysbench的其他特性

上一篇 下一篇

猜你喜欢

热点阅读