如何在给定时间段内调整此Mysql查询以计算消耗?

时间:2017-08-07 11:01:31

标签: mysql performance query-optimization

实际表格包含电表的处理数据,我是在每小时处理数据并将其插入processed_data_hourly表格后,在余下的基础上从中采样的电表。

现在我要做的是根据客户选择的日期和时间段显示报告processed_data_hourly

下面的查询给出了我想要的预期输出,但是执行大约70到90秒需要花费很多时间。

所以任何人都可以帮我优化这个查询,以便执行时间更短

Query :

    SELECT
        A.node_id,
        A.start_time,
        B.end_time,
        A.startReadingIMP,
        B.endReadingIMP,
        (B.endReadingIMP - A.startReadingIMP) diffIMP
    FROM
        ((SELECT
        node_id, start_time, end_time, srv_vah startReadingIMP
    FROM
        processed_data_hourly
    WHERE
        start_time >= '2017-05-15 00:00:00'
            AND end_time <= '2017-05-15 23:59:59'
    GROUP BY node_id
    ORDER BY start_time ASC) AS A, (SELECT
        node_id, start_time, end_time, erv_vah endReadingIMP
    FROM
        processed_data_hourly
    WHERE
        start_time >= '2017-05-15 00:00:00'
            AND end_time <= '2017-05-15 23:59:59'
    GROUP BY end_time DESC) AS B
   )
    WHERE
        A.node_id = 6 and B.node_id=6

    GROUP BY A.node_id , B.node_id

预期产量: Output

表格结构

Table Structure

P.S:表格结构太大而无法发布,因为它包含大量列

1 个答案:

答案 0 :(得分:0)

首先,您的查询中存在语法错误:

    WHERE
        start_time >= '2017-05-15 00:00:00'
            AND end_time <= '2017-05-15 23:59:59'
    GROUP BY end_time DESC) AS B
   )

不允许DESC列表之后的group by子句。

我想它应该是GROUP BY node_id ORDER BY end_time DESC

如果我的问题是正确的,那么我的第二句话是您的查询使用MySQL Group by extenstion。根据文件:

  

如果禁用ONLY_FULL_GROUP_BY,则为标准的MySQL扩展   GROUP BY的SQL使用允许选择列表,HAVING条件或   ORDER BY列表引用非聚合列,即使列   在功能上不依赖于GROUP BY列。这会导致MySQL   接受前面的查询。在这种情况下,服务器是免费的   从每个组中选择任何值,所以除非它们相同,否则   选择的值是不确定的,这可能不是你想要的。   此外,不能从每个组中选择值   受添加ORDER BY子句影响。结果集排序发生   选择值后,ORDER BY不会影响哪个   服务器选择的每个组中的值。禁用   ONLY_FULL_GROUP_BY主要是因为有些人知道这一点   数据的属性,每个非聚合列中的所有值都不是   在GROUP BY中命名的每个组都是相同的。

有人可能会说,实际上你的查询是从表中挑选随机行 您可以在这个简单的演示中观察到:SQLFiddle

SELECT * FROM processed_data_hourly;

| node_id |           start_time |             end_time | srv_vah | erv_vah |
|---------|----------------------|----------------------|---------|---------|
|       6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z |      11 |     111 |
|       6 | 2017-05-15T00:05:00Z | 2017-05-15T00:12:00Z |      22 |     222 |
|       6 | 2017-05-15T00:04:00Z | 2017-05-15T00:13:00Z |      33 |     333 |
|       6 | 2017-05-15T00:07:00Z | 2017-05-15T00:10:00Z |      44 |     444 |
|       6 | 2017-05-15T00:08:00Z | 2017-05-15T00:21:00Z |      55 |     555 |
SELECT
        A.node_id,
        A.start_time,
        B.end_time,
        A.startReadingIMP,
        B.endReadingIMP,
        (B.endReadingIMP - A.startReadingIMP) diffIMP
    FROM
        ((SELECT
        node_id, start_time, end_time, srv_vah startReadingIMP
    FROM
        processed_data_hourly
    WHERE
        start_time >= '2017-05-15 00:00:00'
            AND end_time <= '2017-05-15 23:59:59'
    GROUP BY node_id
    ORDER BY start_time ASC) AS A, (SELECT
        node_id, start_time, end_time, erv_vah endReadingIMP
    FROM
        processed_data_hourly
    WHERE
        start_time >= '2017-05-15 00:00:00'
            AND end_time <= '2017-05-15 23:59:59'
    GROUP BY node_id
    ORDER BY end_time DESC) AS B
   )
    WHERE
        A.node_id = 6 and B.node_id=6
    GROUP BY A.node_id , B.node_id

| node_id |           start_time |             end_time | startReadingIMP | endReadingIMP | diffIMP |
|---------|----------------------|----------------------|-----------------|---------------|---------|
|       6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z |              11 |           111 |     100 |

如果你分析上面的结果,你可以看到两个子查询都选择了第一行,即:

| node_id |           start_time |             end_time | srv_vah | erv_vah |
|---------|----------------------|----------------------|---------|---------|
|       6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z |      11 |     111 |

如果这确实是您想要的结果,您可以将查询重写为另一个按id, start_time对表格进行排序的查询,并为每个id选择第一行,例如:

SELECT node_id,
       start_time,
       end_time,
       srv_vah As startReadingIMP,
       erv_vah As endReadingIMP,
       erv_vah - srv_vah As diffIMP 
FROM processed_data_hourly a
WHERE NOT EXISTS (
  SELECT *
  FROM processed_data_hourly b
  WHERE a.node_id = b.node_id
    AND b.start_time < a.start_time
);

| node_id |           start_time |             end_time | startReadingIMP | endReadingIMP | diffIMP |
|---------|----------------------|----------------------|-----------------|---------------|---------|
|       6 | 2017-05-15T00:01:00Z | 2017-05-15T00:14:00Z |              11 |           111 |     100 |

演示:http://sqlfiddle.com/#!9/8faefc/5

接下来,如果您在node_id, start_time上添加索引,那么此查询应该非常快。