使用 sysbench 对 MySQL 进行性能测试,测试结果示例:
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 1000
Report intermediate results every 10 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
[ 10s ] thds: 1000 tps: 373.36 qps: 9083.26 (r/w/o: 6656.54/1576.82/849.90) lat (ms,95%): 5507.54 err/s: 3.30 reconn/s: 0.00
[ 20s ] thds: 1000 tps: 451.51 qps: 9174.67 (r/w/o: 6450.09/1813.15/911.43) lat (ms,95%): 5312.73 err/s: 8.30 reconn/s: 0.00
[ 30s ] thds: 1000 tps: 492.89 qps: 9980.35 (r/w/o: 6996.99/1989.57/993.78) lat (ms,95%): 4855.31 err/s: 8.00 reconn/s: 0.00
[ 40s ] thds: 1000 tps: 466.71 qps: 9441.82 (r/w/o: 6635.78/1866.12/939.91) lat (ms,95%): 4683.57 err/s: 6.50 reconn/s: 0.00
[ 50s ] thds: 1000 tps: 479.69 qps: 9695.32 (r/w/o: 6804.47/1925.46/965.38) lat (ms,95%): 5217.92 err/s: 6.00 reconn/s: 0.00
[ 60s ] thds: 1000 tps: 417.20 qps: 8438.40 (r/w/o: 5920.83/1677.18/840.39) lat (ms,95%): 5709.50 err/s: 6.70 reconn/s: 0.00
[ 70s ] thds: 1000 tps: 449.92 qps: 9146.85 (r/w/o: 6425.35/1812.87/908.63) lat (ms,95%): 5124.81 err/s: 8.10 reconn/s: 0.00
[ 80s ] thds: 1000 tps: 299.10 qps: 6028.05 (r/w/o: 4231.84/1195.11/601.11) lat (ms,95%): 6960.17 err/s: 2.90 reconn/s: 0.00
[ 90s ] thds: 1000 tps: 289.60 qps: 5834.17 (r/w/o: 4092.68/1159.39/582.10) lat (ms,95%): 7895.16 err/s: 2.90 reconn/s: 0.00
[ 100s ] thds: 1000 tps: 275.20 qps: 5544.43 (r/w/o: 3881.55/1109.09/553.79) lat (ms,95%): 7895.16 err/s: 3.40 reconn/s: 0.00
[ 110s ] thds: 1000 tps: 246.20 qps: 5013.35 (r/w/o: 3531.14/985.21/497.01) lat (ms,95%): 9284.15 err/s: 4.60 reconn/s: 0.00
[ 120s ] thds: 1000 tps: 238.20 qps: 4827.83 (r/w/o: 3390.72/956.81/480.30) lat (ms,95%): 9452.83 err/s: 3.90 reconn/s: 0.00
[ 130s ] thds: 1000 tps: 279.89 qps: 5641.99 (r/w/o: 3950.72/1127.88/563.39) lat (ms,95%): 8638.96 err/s: 3.60 reconn/s: 0.00
[ 140s ] thds: 1000 tps: 240.90 qps: 4905.55 (r/w/o: 3451.64/967.71/486.21) lat (ms,95%): 9452.83 err/s: 4.40 reconn/s: 0.00
[ 150s ] thds: 1000 tps: 301.80 qps: 6083.81 (r/w/o: 4264.24/1212.98/606.59) lat (ms,95%): 8955.74 err/s: 3.90 reconn/s: 0.00
[ 160s ] thds: 1000 tps: 310.59 qps: 6275.97 (r/w/o: 4407.81/1242.57/625.59) lat (ms,95%): 7215.39 err/s: 3.50 reconn/s: 0.00
[ 170s ] thds: 1000 tps: 292.11 qps: 5927.00 (r/w/o: 4161.54/1176.44/589.02) lat (ms,95%): 8333.38 err/s: 4.80 reconn/s: 0.00
[ 180s ] thds: 1000 tps: 307.89 qps: 6213.57 (r/w/o: 4360.81/1233.27/619.49) lat (ms,95%): 7346.49 err/s: 3.70 reconn/s: 0.00
SQL statistics:
queries performed:
read: 896238 # 读请求数,占总查询 70%
write: 253492 # 写请求数,占总查询 20%
other: 127145 # 其他请求,占总查询 10%
total: 1276875 # 请求数总和,等于下面的 Queries
transactions: 63128 (345.34 per sec.) # 事务数与 TPS
queries: 1276875 (6985.20 per sec.) # 请求数与 QPS
ignored errors: 889 (4.86 per sec.) # 忽略错误数
reconnects: 0 (0.00 per sec.) # 重连数
General statistics:
total time: 182.7966s # 总时间
total number of events: 63128 # 总事件,这里等于事务数
Latency (ms):
min: 30.69 # 最低时延
avg: 2874.65 # 平均时延
max: 20481.61 # 最高时延
95th percentile: 7346.49 # 95% 时延低于
sum: 181470972.53 # 总时延
Threads fairness:
events (avg/stddev): 63.1280/5.92 # 平均线程事件
execution time (avg/stddev): 181.4710/0.67 # 平均线程执行时间
测试机器原为腾讯云服务器,但远程测试容易发生错误,让 sysbench 无法断开连接准时停止,同时服务器配置为至强(2 核 4 线程)+ 4G 内存 + 50G 存储。性能并不好,后面选择使用自己的机器 + docker 来搭建 MySQL 服务,配置为 AMD 4800U(8 核 16 线程)+ 16G 内存 + 512G 存储。
综合性能测试
综合性能测试包含 select
、update
、insert
和 delete
。
单表并发测试
数据量:100000,测试时间:180s,事务比例:5%。测试命令示例:
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--mysql-db=sysbench \
--mysql-user=sysbench \
--mysql-password=123456 \
--mysql-port=3306 \
--mysql-host=127.0.0.1 \
--oltp-tables-count=1 \
--oltp-table-size=100000 \
--threads=100 \
--time=180 \
--report-interval=10 \
run
并发线程 | 总请求数 | QPS | 平均延迟 | 95th 百分比时延 |
---|---|---|---|---|
10 | 695420 | 3862.68 | 51.76 | 73.13 |
100 | 2470033 | 13710.58 | 145.81 | 235.74 |
200 | 2888346 | 16018.62 | 249.41 | 411.96 |
500 | 2534984 | 14013.10 | 712.64 | 1973.38 |
800 | 1587282 | 8739.79 | 1835.75 | 4943.53 |
1000 | 1276875 | 6985.20 | 2874.65 | 7346.49 |
more | x | x | x | x |
多表并发测试
数据量:100000,测试时间:180s,事务比例:5%。测试命令示例:
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--mysql-db=sysbench \
--mysql-user=sysbench \
--mysql-password=123456 \
--mysql-port=3306 \
--mysql-host=127.0.0.1 \
--oltp-tables-count=10 \
--oltp-table-size=100000 \
--threads=100 \
--time=180 \
--report-interval=10 \
run
并发线程 | 总请求数 | QPS | 平均延迟 | 95th 百分比时延 |
---|---|---|---|---|
10 | 508440 | 2823.90 | 70.81 | 95.81 |
100 | 2089060 | 11597.23 | 172.40 | 257.95 |
200 | 2116297 | 11741.18 | 340.51 | 1191.92 |
500 | 2743844 | 15168.02 | 657.79 | 1069.86 |
800 | 2120840 | 11633.67 | 1360.01 | 3208.88 |
1000 | 2602186 | 14375.65 | 1388.81 | 2159.29 |
more | x | x | x | x |
单表数据量测试
线程数:200,测试时间:180s,事务比例:5%。测试命令示例:
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--mysql-db=sysbench \
--mysql-user=sysbench \
--mysql-password=123456 \
--mysql-port=3306 \
--mysql-host=127.0.0.1 \
--oltp-tables-count=1 \
--oltp-table-size=50000000 \
--threads=200 \
--time=180 \
--report-interval=10 \
run
数据量 | 总请求数 | QPS | 平均延迟 | 95th 百分比时延 | 最大时延 | 最小时延 |
---|---|---|---|---|---|---|
10k | 501296 | 2764.85 | 1512.96 | 2040.14 | 8948.01 | 37.82 |
100k | 2957386 | 16400.41 | 243.67 | 397.39 | 1087.80 | 69.51 |
1m | 2621480 | 14545.32 | 274.85 | 434.83 | 2234.68 | 45.53 |
5m | 1969960 | 10935.26 | 365.59 | 601.29 | 9762.25 | 40.08 |
10m | 1452980 | 8054.12 | 495.96 | 877.61 | 17556.62 | 40.45 |
50m | 179200 | 982.94 | 4043.12 | 15650.42 | 54546.98 | 69.09 |
100m | 176740 | 970.81 | 4100.72 | 14302.94 | 49566.81 | 54.09 |
- 当数据量太少时,并发太容易产生锁,因此 QPS 非常低。
- 当数据量达到数十万时,并发执行的效果最好,此时 QPS 较高,延迟较低。
- 当数据量超百万时,QPS 开始逐渐下降,超千万时下降尤为明显。
由此可得出简单推论,单表数据量最好保持十万级,此时综合性能最好。
读性能测试
线程数:200,测试事件:180s,事务比例:0.0625,测试命令示例:
sysbench /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua \
--db-driver=mysql \
--mysql-db=sysbench \
--mysql-user=sysbench \
--mysql-password=123456 \
--mysql-port=3306 \
--mysql-host=127.0.0.1 \
--oltp-tables-count=1 \
--oltp-table-size=1000000 \
--oltp-read-only=on \
--threads=200 \
--time=180 \
--report-interval=10 \
run
数据量 | 总请求数 | QPS | 平均延迟 | 95th 百分比时延 | 最大时延 | 最小时延 |
---|---|---|---|---|---|---|
10k | 4266240 | 23685.39 | 125.05 | 167.44 | 375.75 | 55.05 |
100k | 4101120 | 22766.96 | 140.49 | 173.58 | 352.82 | 65.41 |
1m | 4255184 | 23623.67 | 135.40 | 167.44 | 432.21 | 48.31 |
5m | 3864544 | 21453.53 | 149.10 | 204.11 | 36.91 | 427.68 |
10m | 3650672 | 20267.05 | 157.82 | 219.36 | 420.52 | 38.01 |
50m | 3376352 | 18742.69 | 170.67 | 240.02 | 906.25 | 31.00 |
100m | 3249920 | 18039.97 | 177.31 | 248.84 | 613.14 | 47.80 |
可以看到,200 连接时,单机单表最高可以抗两万多的读 QPS,而综合操作最高抗一万六左右的 QPS,同时只读的时延非常低,因此对于并发要求高的场景,分库分表是非常必要的。