通过算术和几何计算加快 SQL SELECT
Speed up SQL SELECT with arithmetic and geometric calculations
这是我之前 post .
的后续
我扩展了 SQL 语句,以使用 circular statistics 执行计算平均风向的第一部分。这意味着我要计算风向的余弦和正弦的平均值。在我的 PHP 脚本中,我将执行第二部分并计算反正切并在必要时添加 180 或 360 度。
风向存储在我的 table 中,作为从现场传感器读取的电压 '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
根据我用来对数据分组的值(上面代码中的 300),查询 运行 大约需要 3-8 秒。
为了让我学习,我可以做些什么来优化或改进 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;
解释:你所拥有的无法使用索引,因此必须扫描整个 table(越来越大)。我的子查询可以使用索引,因此速度要快得多。我的外部查询的工作不是 "too bad",因为它只处理 N 行。
这是我之前 post
我扩展了 SQL 语句,以使用 circular statistics 执行计算平均风向的第一部分。这意味着我要计算风向的余弦和正弦的平均值。在我的 PHP 脚本中,我将执行第二部分并计算反正切并在必要时添加 180 或 360 度。
风向存储在我的 table 中,作为从现场传感器读取的电压 '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
根据我用来对数据分组的值(上面代码中的 300),查询 运行 大约需要 3-8 秒。
为了让我学习,我可以做些什么来优化或改进 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;
解释:你所拥有的无法使用索引,因此必须扫描整个 table(越来越大)。我的子查询可以使用索引,因此速度要快得多。我的外部查询的工作不是 "too bad",因为它只处理 N 行。