2015-04-27 36 views
0

这是我以前的帖子How to improve wind data SQL query performance的后续。使用算术和几何计算加速SQL SELECT

我已经扩展了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语句,否则?

+0

您正在使用哪个数据库? – ipinak

+0

我猜你仍然使用与链接到的问题相同的数据库... –

+0

你可以在该查询上运行'EXPLAIN'吗? –

回答

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行,所以我的外部查询的工作并不是“太糟糕”。

+0

谢谢瑞克,我非常感谢你的帮助!我确实将dt添加为主索引。用嵌套的SELECT替换LIMIT(仅用于创建6小时的数据)到您的建议之后,查询的执行时间从4.2秒减少到0.008。惊人!我将重写分页实现以代替dt。 – Watts