BENCHMARK()函数( https://dev.mysql.com/doc/refman/5.7/en/select-benchmarking.html )是MySQL的一个内置函数,用于测试函数或者表达式的执行速度。用法很简单,接受两个参数BENCHMARK(loop_count, expression):即执行expression一共loop_count次。BENCHMARK()的返回值总是0,但是mysql客户端会打印一行来输出语句的大概执行时间。
mysql> SELECT BENCHMARK(1000000, AES_ENCRYPT('hello','goodbye')); +----------------------------------------------------+ | BENCHMARK(1000000, AES_ENCRYPT('hello','goodbye')) | +----------------------------------------------------+ | 0 | +----------------------------------------------------+ 1 row in set (0.28 sec)
BENCHMARK()是一个用来找出导致查询出现性能问题的方法或表达式的优良公举。参考https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_benchmark,以下是其使用说明。
mysql> SELECT BENCHMARK(1000000, (SELECT COUNT(*) FROM information_schema.`TABLES` t)); +--------------------------------------------------------------------------+ | BENCHMARK(1000000, (SELECT COUNT(*) FROM information_schema.`TABLES` t)) | +--------------------------------------------------------------------------+ | 0 | +--------------------------------------------------------------------------+ 1 row in set (0.05 sec) mysql> SELECT BENCHMARK(1000000, 'SELECT COUNT(*) FROM information_schema.`TABLES` t'); +--------------------------------------------------------------------------+ | BENCHMARK(1000000, 'SELECT COUNT(*) FROM information_schema.`TABLES` t') | +--------------------------------------------------------------------------+ | 0 | +--------------------------------------------------------------------------+ 1 row in set (0.01 sec)
mysql> SELECT BENCHMARK(1000000, (SELECT t.TABLE_NAME FROM information_schema.`TABLES` t)); ERROR 1242 (21000): Subquery returns more than 1 row mysql> SELECT BENCHMARK(1000000, (SELECT t.TABLE_NAME, t.TABLE_SCHEMA FROM information_schema.`TABLES` t)); ERROR 1241 (21000): Operand should contain 1 column(s)
SELECT expr
语句N
次和执行SELECT BENCHMARK(N
,expr
)
的消耗并不是一样的,二者有截然不同的执行情况所以不能指望它们花费一样的时间量:前者是计算 N
次包含解析器、优化器、锁以及执行查询在内的时间消耗;后者只计算N
次执行查询时间,其他部分则只计算一次。相较简单的BENCHMARK()函数,mysqlslap应该才算得上是真正意义上的基准测试工具。“mysqlslap”是MySQL自带的命令行小公举之一(https://dev.mysql.com/doc/refman/5.7/en/mysqlslap.html),设计用于模仿一台MySQL服务器的客户端负载并以此来测试计时。它运行的时候就像多个客户端在并发访问。
调用mysqlslap如下(可以在终端键入mysqlslap --help查看详细参数信息):
shell> mysqlslap [options]
mysqlslap --help mysqlslap: [ERROR] unknown variable 'default-character-set=utf8' vim /etc/mysql/mysql.conf.d/mysqld.cnf [mysql] default-character-set=utf8
我本地的Ubuntu Linux出现了字符报错,去配置文件看了一下,默认字符集设置放到了[client]组下面了,把它移到[mysql]组下面就OK了。
一些options,比如--create和--query接受一个包含SQL语句的字符串或者文件。如果指定的是文件,默认情况下必须一行一句SQL(即隐式分隔符是换行符)。不过可以通过--delimiter选项另外指定一个分隔符,这样一行就可以放多句SQL了。但是需要注意的是,文件里面不能包含注释语句,mysqlslap程序无法识别。
mysqlslap运行分为三个步骤:
①创建库、表以及视选项加载存储程序和测试用数据。这一步在单个客户端连接下。
②进行负载测试。这一步可以在多客户端连接下。
③清场(断开连接、如果指定了则删除测试用表)。这一步在单个客户端连接下。
进行一些测试实例吧。
mysqlslap --user=root --password=520 \ --delimiter=";" \ --create="CREATE TABLE a (b int);INSERT INTO a VALUES (23)" \ --query="SELECT * FROM a" --concurrency=50 --iterations=200
Benchmark Average number of seconds to run all queries: 0.016 seconds Minimum number of seconds to run all queries: 0.008 seconds Maximum number of seconds to run all queries: 0.093 seconds Number of clients running queries: 50 Average number of queries per client: 1
mysqlslap --user=root --password=520 \ --concurrency=5 --iterations=20 \ --number-int-cols=2 --number-char-cols=3 \ --auto-generate-sql
Benchmark Average number of seconds to run all queries: 0.062 seconds Minimum number of seconds to run all queries: 0.017 seconds Maximum number of seconds to run all queries: 0.185 seconds Number of clients running queries: 5 Average number of queries per client: 0
echo -e 'DROP DATABASE IF EXISTS `benchmarker`; CREATE DATABASE `benchmarker`; CREATE TABLE `benchmarker`.`tables` LIKE `information_schema`.`TABLES`; INSERT INTO `benchmarker`.`tables` SELECT * FROM `information_schema`.`TABLES`; CREATE TABLE `benchmarker`.`columns` LIKE `information_schema`.`COLUMNS`; INSERT INTO `benchmarker`.`columns` SELECT * FROM `information_schema`.`COLUMNS`;' > create.sql
echo -e 'SELECT * FROM `benchmarker`.`tables`; SELECT * FROM `benchmarker`.`columns`;' > query.sql
mysqlslap --user=root --password=520 \ --concurrency=5 \ --iterations=5 --query=query.sql --create=create.sql \ --delimiter=";"
Benchmark Average number of seconds to run all queries: 0.058 seconds Minimum number of seconds to run all queries: 0.047 seconds Maximum number of seconds to run all queries: 0.067 seconds Number of clients running queries: 5 Average number of queries per client: 2
测试打印结果会以“Benchmark”行开始,分别给出了运行所有查询的平均时间以及相应的极小值和极大值。执行查询的客户端数是由选项--concurrency指定的,最后是每个客户端的平均执行查询次数(执行多少个查询)。可以看出,mysqlslap是一款小巧实用的并发查询性能测试工具,适合于表设计和查询调优的场景。