mysql/mariadb 查询的耗时不一致

mysql/mariadb 查询的耗时不一致

检查 munin 监控的数据库查询所用的时间,我创建了一个脚本,时间测量部分如下:

start=$(sed 's/^0*//'<<< `date +%N`)
/usr/bin/mysql -u 3da_d9 -p****** --host="127.0.0.1" --port=4002 -e "SELECT f.*, AVG(l.value) AS vote_value, COUNT(l.value) AS vote_count, 0 AS active_feature, c.name from 3dallusions_joomla_d9.jom3_downloads_files AS f INNER JOIN 3dallusions_joomla_d9.jom3_downloads_containers AS c ON f.containerid = c.id LEFT JOIN 3dallusions_joomla_d9.jom3_downloads_log AS l ON l.type = 3 AND l.fileid = f.id AND l.value != 0" > /dev/null
end=$(sed 's/^0*//'<<< `date +%N`)
if [ "$end" -lt "$start" ]; then
    end=$(($end+1000000000))
fi
elapsed=$(($end - $start))
elapsed=$(($elapsed/1000000))
echo $elapsed

我通过将 SQL 调用替换为简单的 sleep 来检查时间测量的逻辑。每次都会给出一致的结果。

数据库和客户端是来自 Debian Stretch 存储库的 MariaDB 10.1。

让我感到困惑的是,第一次运行脚本时,答案大约是 10 毫秒。后续运行给出的结果大约是 50 毫秒。在停止运行脚本一段时间后,再次得到大约 10 毫秒的结果。

为什么第一次查询比重复查询快 5 倍?人们可能认为缓存会产生相反的效果。发生了什么?

答案1

查看您正在执行的开销——日期、sed、mysql、mysql 登录等。

相反,应尽可能在操作接近时进行日期检查:

SELECT @start := SYSDATE(6), log(10), @end := SYSDATE(6);
SELECT UNIX_TIMESTAMP(@end) - UNIX_TIMESTAMP(@start) AS 'seconds';

+----------+
| seconds  |
+----------+
| 0.000037 |
+----------+

这就是说 37 微秒,但仍然有很多开销。

还请考虑以下BENCHMARK功能:

mysql> SELECT BENCHMARK(1000000, log(10));
+-----------------------------+
| BENCHMARK(1000000, log(10)) |
+-----------------------------+
|                           0 |
+-----------------------------+
1 row in set (0.03 sec)

这说明 0.03 微秒;我相信它。 BENCHMARK是对函数或表达式进行计时的方式。

如果你可以使用 PHP,那么只需执行

$start = microtime(true);
... perform the query ...
$end = microtime(true);
echo $end - $start, ' seconds';

对于完整的陈述来说,这已经‘足够好’了。

相关内容