2015-04-22 61 views
0

我正在寻找如何通过更改(例如)如何优化(如果可能)用于阅读风信息的SQL查询的性能的帮助(请参见下文)。数据库结构,查询或其他东西?如何提高风数据SQL查询性能

我使用托管数据库来存储具有超过800,000行风况信息(速度和方向)的表格。从风速计每分钟添加一次新数据。使用PHP脚本访问数据库,该脚本创建一个网页,用于使用Google的可视化API绘制数据。

该网页大约需要15秒才能加载。我已在PHPJavascript部分中添加了一些时间度量,以分析代码并找出可能需要改进的地方。

我希望改进的一个部分是下面的查询,它大约需要4秒的时间来执行。查询的目的是将15分钟的风速(最小/最大/平均值)分组,并计算测量期间的平均值和总的最小/最大值。

SELECT AVG(d_mean) AS group_mean, 
     MAX(d_max) as group_max, 
     MIN(d_min) AS 
     group_min, 
     dir, 
     FROM_UNIXTIME(MAX(dt),'%Y-%m-%d %H:%i') AS group_dt 
FROM (
    SELECT @i:[email protected]+1, 
      FLOOR(@i/15) AS group_id, 
      CAST(mean AS DECIMAL(3,1)) AS d_mean, 
      CAST(min AS DECIMAL(3,1)) AS d_min, 
      CAST(max AS DECIMAL(3,1)) AS d_max, 
      dir, 
      UNIX_TIMESTAMP(STR_TO_DATE(dt, '%Y-%m-%d %H:%i')) AS dt 
      FROM table, (SELECT @i:=-1) VAR_INIT 
      ORDER BY id DESC 
) AS T 
GROUP BY group_id 
LIMIT 0, 360 

... 

$oResult = mysql_query($sSQL); 

该表具有以下结构:

1 ID  int(11)  AUTO_INCREMENT 
2 mean varchar(5) utf8_general_ci 
3 max  varchar(5) utf8_general_ci 
4 min  varchar(5) utf8_general_ci 
5 dt  varchar(20) utf8_general_ci // Date and time 
6 dir  varchar(5) utf8_general_ci 

以下设置用于:

  • 数据库:MariaDB的,42年5月5日-MariaDB的-1〜喘息
  • 数据库客户端版本:libmysql - 5.1.66
  • PHP版本:5.6
  • PHP的扩展:mysqli
+1

'5 DT VARCHAR(20)utf8_general_ci //日期和time'不要储存日期+时间在一个字符字段。使用日期时间或时间戳(如果可用)并且类似于速度和方向:使用整数,数字或甚至浮点类型,但不使用**字符类型来存储它们。 – wildplasser

+1

你可以发布解释和数据模型吗?另外:请格式化你的代码,使其变得更可读。 –

+0

您的问题的很大一部分可能是隐式转换。这也会让您在查询时出现不必要的错误风险。只有80万行可能不是什么大问题,但仍然是一个问题。和糟糕的设计。 –

回答

1

我非常同意目前的意见 - 清理数据,因为你把它放到表中。

一旦你做清洁,让我们避免子查询做...

SELECT MIN(dt) as 'Start of 15 mins', 
     FORMAT(AVG(mean), 1) as 'Avg wind speed', 
     ... 
    FROM table 
    GROUP BY FLOOR(UNIX_TIMESTAMP(dt)/900) 
    ORDER BY FLOOR(UNIX_TIMESTAMP(dt)/900); 

我不明白LIMIT的目的。我猜你一天想要几天。为此,我建议您在FROMGROUP BY之间添加(之后清洁)。

WHERE dt >= '2015-04-10' 
     AND dt < '2015-04-10' + INTERVAL 7 DAY 

这将显示7天,从'2015-04-10'上午开始。

为了处理的800K一个表,你会决然需要(再次,清洗):

INDEX(dt) 

来清洁800K行,有多种方法。我建议创建一个新表,复制数据,测试并最终交换。类似...

CREATE TABLE new (
    dt DATETIME, 
    mean FLOAT, 
    ... 
    PRIMARY KEY(dt) -- assuming you have only one row per minute? 
) ENGINE=InnoDB; 

INSERT INTO new (dt, mean, ...) 
    SELECT str_to_date(...), 
      mean, -- I suspect that the CAST is not needed 
      ...; 

编写新的选择并测试它。

现在new缺少较新的行。您可以重建它,并希望在一分钟内完成所有事情,或者玩其他游戏。让我们知道你是否需要帮助。

+0

对于不清楚细节,我感到抱歉。你对使用LIMIT的假设是正确的。 – Watts

+0

我制作了一份表格的副本,然后我遵循了您的建议,并更改了表格中的两种数据类型,并重写了SQL查询。一切正常。至于性能,查询执行速度大约为1秒左右,所以它的大约是。快25%。 – Watts

+0

我错过了INDEX(dt)部分。你能否解释一下这个目的是什么?这是一次性的任务,通过运行查询,如“CREATE INDEX index_name ON table_name(column_name);”?索引是我应该使用的东西,还是数据库的内部问题? – Watts