使用舍入的主日期时间键进行MySQL改进

时间:2018-03-24 20:55:53

标签: mysql performance

我正在通过首先对其主日期时间键进行舍入来处理从一个数据库连接多个表的查询。数据库包含来自openhab的percistance数据,每个表只有一个名为Time的主Datetime行和一个名为Value的值行。随着日期被写入,可能发生一秒的小延迟,并且我无法直接比较主键。这是我到目前为止所得到的:

SELECT FROM_UNIXTIME(((UNIX_TIMESTAMP(i1.Time)+30)DIV 60)*60) AS rounded_time,i1.Value,i2.Value,i4.Value,i5.Value 
FROM item1 i1,item2 i2,item4 i4,item5 i5
WHERE
(((UNIX_TIMESTAMP(i1.Time)+30)DIV 60)*60) = (((UNIX_TIMESTAMP(i2.Time)+30)DIV 60)*60) AND
(((UNIX_TIMESTAMP(i1.Time)+30)DIV 60)*60) = (((UNIX_TIMESTAMP(i4.Time)+30)DIV 60)*60) AND 
(((UNIX_TIMESTAMP(i1.Time)+30)DIV 60)*60) = (((UNIX_TIMESTAMP(i5.Time)+30)DIV 60)*60) AND 
UNIX_TIMESTAMP(i1.Time) > UNIX_TIMESTAMP(date_sub(now(), interval 1 day));

这个查询已经需要4秒钟,并且合并了另外一个项目已经破坏了我的服务器。

Details

Expected Result

Explain Result

编辑1: 通过在两个方向上允许60秒的偏移量,我设法通过以下连接获得合理的结果(如果两者都需要,则甚至不是舒适的):

SELECT date_format(item1.Time, '%Y-%m-%d %H:%i') AS TIME,item1.Value AS I_TEMP,item2.Value AS I_HUM,item4.Value AS I_PRESS,item5.Value AS I_LIGHT,item6.Value AS O_HUM,item7.Value AS O_TEMP,item8.Value AS O_PRESS
FROM item1
LEFT JOIN item2 ON (item2.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item2.time AND date_add(item2.time, interval 60 SECOND))
LEFT JOIN item4 ON (item4.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item4.time AND date_add(item4.time, interval 60 SECOND))
LEFT JOIN item5 ON (item5.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item5.time AND date_add(item5.time, interval 60 SECOND))
LEFT JOIN item6 ON (item6.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item6.time AND date_add(item6.time, interval 60 SECOND))
LEFT JOIN item7 ON (item7.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item7.time AND date_add(item7.time, interval 60 SECOND))
LEFT JOIN item8 ON (item8.time BETWEEN item1.time AND date_add(item1.time, interval 60 SECOND)) OR (item1.time BETWEEN item8.time AND date_add(item8.time, interval 60 SECOND))
WHERE
item1.Time > date_sub(now(), interval 3 HOUR)

此外,INDEXING的工作方式如here所示,感谢Rick James,查询时间相当短暂。

1 个答案:

答案 0 :(得分:0)

在处理这个问题之前,我对它的有效性非常怀疑。如果我的时间是08:09:29而不是08:09:31,那么它们相距仅2秒,但是你的&#34;舍入&#34;技术会说他们是不同的。您需要TIMEDIFF(...) < 30之类的内容来避免错误&#39;。

解决您的效果问题...这不能使用任何索引:

UNIX_TIMESTAMP(i1.Time) > UNIX_TIMESTAMP(date_sub(now(), interval 1 day));

改为:

i1.Time > now() - interval 1 day

您可以使用:

INDEX(Time)

这将可能加速查询。

但是......有一个更糟糕的问题。你正在做一个&#34;交叉加入&#34;。这意味着将比较4个表中所有行的组合。如果每个行只有1000行,则组合一万亿

也许你需要JOIN ... ON ...