没有附加列的子查询比列更长

时间:2016-07-14 15:35:10

标签: mysql sql subquery cumulative-sum metabase

我正在尝试使用子查询获得总计。 (我正在使用Metabase,它似乎不接受/处理查询中的变量)

我的查询:

SELECT date_format(t.`session_stop`, '%d') AS `session_stop`, 
    sum(t.`energy_used` / 1000) AS `csum`,
    (
      SELECT (SUM(a.`energy_used`) / 1000)
      FROM `sessions` a 
      WHERE date_format(a.`session_stop`, '%Y-%m-%d') <=  date_format(t.`session_stop`, '%Y-%m-%d') 
      AND str_to_date(concat(date_format(a.`session_stop`, '%Y-%m'), '-01'), '%Y-%m-%d') = str_to_date(concat(date_format(now(), '%Y-%m'), '-01'), '%Y-%m-%d')
      ORDER BY str_to_date(date_format(a.`session_stop`, '%e'), '%d') ASC
    ) AS `sum`
    FROM `sessions` t
    WHERE str_to_date(concat(date_format(t.`session_stop`, '%Y-%m'), '-01'), '%Y-%m-%d') = str_to_date(concat(date_format(now(), '%Y-%m'), '-01'), '%Y-%m-%d')
    GROUP BY date_format(t.`session_stop`, '%e')
    ORDER BY str_to_date(date_format(t.`session_stop`, '%d'), '%d') ASC;

这需要大约1.29秒才能运行。 (总共43K行,返回14)

如果我删除sum(t.`energy_used` / 1000) AS `csum`,行,则查询占用8分钟和40秒。

这是为什么?我宁愿没有那条线,但我也不能等待8分钟来处理查询。

(我知道我可以创建一个累积列,但我特别感兴趣的是为什么这个额外的sum()加快了整个查询的速度)

PS。在MySQL控制台和Metabase接口上测试了它。

EXPLAIN查询:

+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows  | Extra
+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------
|  1 | PRIMARY            | t     | ALL  | NULL          | NULL | NULL    | NULL | 42055 | Using where; Using tempora
|  2 | DEPENDENT SUBQUERY | a     | ALL  | NULL          | NULL | NULL    | NULL | 42055 | Using where
+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------
2 rows in set (0.00 sec)

没有额外的sum()

+----+--------------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------+
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                                        |
+----+--------------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------+
|  1 | PRIMARY            | t     | ALL  | NULL          | NULL | NULL    | NULL | 44976 | Using where; Using temporary; Using filesort |
|  2 | DEPENDENT SUBQUERY | a     | ALL  | NULL          | NULL | NULL    | NULL | 44976 | Using where                                  |
+----+--------------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------+
2 rows in set (0.00 sec)

Schema不仅仅是一个表:

session_id (INT, auto incr., prim.key) | session_stop (datetime) | energy_used (INT) |
 1                           | 1-1-2016 10:00:00       | 123456            |
 2                           | 1-1-2016 10:05:00       | 123456            |
 3                           | 1-2-2016 10:10:00       | 123456            |
 4                           | 1-2-2016 12:00:00       | 123456            |
 5                           | 3-3-2016 14:05:00       | 123456            |

关于互联网的一些例子显示使用WHERE子句的ID,但是我的结果很差。

1 个答案:

答案 0 :(得分:1)

您的查询完全不相似。事实上,他们是两极分开。

  

如果我删除总和(t。energy_used / 1000)AS csum,行,查询   需要8分40秒。

使用SUM时,它是一个聚合。 sum(t. energy_used / 1000)会产生完全不同的结果,因为只选择t.energy_used,这就是为什么查询时间存在巨大差异的原因。

还很不清楚为什么要以这种方式比较日期:

WHERE date_format(a.`session_stop`, '%Y-%m-%d') <=      date_format(t.`session_stop`, '%Y-%m-%d') 

为什么在比较之前用date_format转换它们?由于两个表显然都包含相同的数据类型,因此您应该能够a.session_stop <= t.session_stop这两种情况都会更快。

由于它是不等式比较,它不是索引的良好候选者,但您仍然可以尝试在该列上创建索引以查看它是否有任何影响。

回顾一下,性能差异是因为您不仅仅是添加/删除额外的列而是添加/删除聚合。