使用正在加载的子查询优化选择非常慢

时间:2017-10-13 14:33:14

标签: mysql

我有一个有点棘手的SELECT,因为我试图显示必须动态计算的数据。

数据从SmartHome系统记录并显示在可视化解决方案Grafana中。 所以我必须在MySQL中处理所有这些,并且无法真正编辑数据或前端来完成这项工作。

该图表应显示可在UI中选择的时间范围的每日平均温度。 MySQL中的数据是这样的表:

   DEVICE    |       READING       |       VALUE       |       TIMESTAMP
-----------------------------------------------------------------------------
 Thermometer |     temperature     |        20.0       |  2107.10.12 00:12:59
 Thermometer |     temperature     |        20.2       |  2107.10.12 00:24:12
                                  ...

请求首先创建一个虚拟表(不在数据库中),每个完整小时的时间戳大约为10年。 这种情况非常快,而且似乎不是我缓慢提取的原因

之后,我将虚拟表删除到仅在图表中可见时间范围内的值。 在所有这些完整小时时间戳中,我必须运行一个子选择来获取在整个小时之前记录的最后一个温度值。

然后按日分组此值,并计算平均值。 这样,从00:00到23:00,每个完整小时的平均值超过24。 根据不同的湿地,这就是官方平均温度的正常计算方式。

以下是Select Statement:

SELECT 
    filtered.hour as time, 
    AVG((SELECT VALUE
        FROM history
        WHERE READING="temperature" AND DEVICE="Thermometer" AND TIMESTAMP <= filtered.hour
        ORDER BY TIMESTAMP DESC
        LIMIT 1
    )) as value
FROM (
    SELECT calculated.hour as hour FROM (
            SELECT DATE_ADD(DATE_SUB(DATE($__timeTo()), INTERVAL 10 YEAR), INTERVAL t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i HOUR) as hour 
            FROM (SELECT 0 as i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
                     (SELECT 0 as i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
                     (SELECT 0 as i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
                     (SELECT 0 as i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
                     (SELECT 0 as i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
    ) calculated
    WHERE calculated.hour >=  $__timeFrom() AND calculated.hour <= $__timeTo()
) filtered  
GROUP BY DATE(filtered.hour)

对于一周的时间跨度,图表显示需要大约5-10秒。一个月你接近半分钟。 我所有的其他(没有计算的简单提取)图表加载大约或不到一秒钟。

由于我是一个完全没有MySQL的人,刚刚开始为我的智能家居构建一些SELECT,我真的不知道如何改进它。

专业人士的任何想法? :)

1 个答案:

答案 0 :(得分:0)

除非我监督一些非常明显的事情,并且计算每天平均数的结果并不重要,否则你可以真正简化查询并摆脱子查询。这也应该会提高你的速度。

SELECT DATE(`TIMESTAMP`) AS `date`, AVG(`VALUE`) AS `value` FROM `history` WHERE `READING`='temperature' AND `DEVICE`='Thermometer' AND DATE(`TIMESTAMP`) BETWEEN 'date1' AND 'date2'

只需替换date1&amp; date2包含您想要的值,例如2017-10-15