通过算术和几何计算加快 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 行。