这是我上一篇文章 How to improve wind data SQL query performance 的后续文章.
我已经扩展了 SQL 语句,以使用 circular statistics 执行平均风向计算的第一部分。 。这意味着我想计算风向的余弦和正弦的平均值。在我的 PHP 脚本中,我将执行第二部分并计算反正切,并在必要时添加 180 或 360 度。
风向存储在我的表中,因为从“dirvolt”字段中的传感器读取的电压,因此我首先需要将其转换为弧度。
用户可以使用分页功能向后查看历史风力数据,因此使用 LIMIT,其值在我的 PHP 脚本中动态设置。
我的 SQL 语句当前如下所示:
SELECT ROUND(AVG(speed),1) AS speed_mean, MAX(speed) as speed_max,
MIN(speed) AS speed_min, MAX(dt) AS last_dt,
AVG(SIN(2.04*dirvolt-0.12)) as dir_sin_mean,
AVG(COS(2.04*dirvolt-0.12)) as dir_cos_mean
FROM table
GROUP BY FLOOR(UNIX_TIMESTAMP(dt) / 300)
ORDER BY FLOOR(UNIX_TIMESTAMP(dt) / 300) DESC
LIMIT 0, 72
运行查询大约需要 3-8 秒,具体取决于我用于对数据进行分组的值(上面代码中的 300)。
为了让我学习,我可以做些什么来优化或改进 SQL 语句吗?
最佳答案
SHOW CREATE TABLE table;
从中我可以看到您是否已经有 INDEX(dt)
(或同等内容)。这样,我们就可以修改 SELECT
使其速度显着加快。
但首先,将焦点从 72*300 秒的读数更改为日期时间范围,即 6(?)小时。
让我们看看这个查询:
SELECT * FROM table
WHERE dt >= '...' - INTERVAL 6 HOUR
AND dt < '...';
'...'
在两个地方都是相同的日期时间。使用索引运行得足够快吗?
如果是,那么让我们使用它作为子查询来构建最终查询:
SELECT FORMAT(AVG(speed), 1) AS speed_mean,
MAX(speed) as speed_max,
MIN(speed) AS speed_min,
MAX(dt) AS last_dt,
AVG(SIN(2.04*dirvolt-0.12)) as dir_sin_mean,
AVG(COS(2.04*dirvolt-0.12)) as dir_cos_mean
FROM
( SELECT * FROM table
WHERE dt >= '...' - INTERVAL 6 HOUR
AND dt < '...'
) AS x
GROUP BY FLOOR(UNIX_TIMESTAMP(dt) / 300)
ORDER BY FLOOR(UNIX_TIMESTAMP(dt) / 300) DESC;
解释:您所拥有的无法使用索引,因此必须扫描整个表(变得越来越大)。我的子查询可以使用索引,因此速度更快。我的外部查询的工作量并不算“太糟糕”,因为它只处理 N 行。
关于mysql - 通过算术和几何计算加速 SQL SELECT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29906335/