使用算术和几何计算加速SQL SELECT

时间:2015-04-27 21:32:07

标签: mysql sql database-performance mariadb

这是我之前发布的帖子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语句吗?

1 个答案:

答案 0 :(得分:0)

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行。