检查 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';
对于完整的陈述来说,这已经‘足够好’了。