我有一个包含列的表:
CREATE TABLE aggregates (
a VARHCAR,
b VARCHAR,
c VARCHAR,
metric INT
KEY test (a, b, c, metric)
);
如果我进行如下查询:
SELECT b, c, SUM(metric) metric
FROM aggregates
WHERE a IN ('a', 'couple', 'of', 'values')
GROUP BY b, c
ORDER BY b, c
查询需要10秒,解释是:
+----+-------------+------------+-------+---------------+------+---------+------+--------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+------+---------+------+--------+-----------------------------------------------------------+
| 1 | SIMPLE | aggregates | range | test | test | 767 | NULL | 582383 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+------------+-------+---------------+------+---------+------+--------+-----------------------------------------------------------+
如果我也按列/按顺序分组,那么它不需要临时/ filesort,但是我自己在另一个查询中执行相同的操作:
SELECT b, c, SUM(metric) metric
FROM (
SELECT a, b, c, SUM(metric) metric
FROM aggregates
WHERE a IN ('a', 'couple', 'of', 'values')
GROUP BY a, b, c
ORDER BY a, b, c
) t
GROUP BY b, c
ORDER BY b, c
查询需要1秒钟,解释是:
+----+-------------+------------+-------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+------+---------+------+--------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 252 | Using temporary; Using filesort |
| 2 | DERIVED | aggregates | range | test | test | 767 | NULL | 582383 | Using where; Using index |
+----+-------------+------------+-------+---------------+------+---------+------+--------+---------------------------------+
这是为什么?如果我在一个单独的外部查询中进行分组,而不是只在一个中进行分组,为什么它会更快?
答案 0 :(得分:2)
SQL的工作方式是每个步骤的数据越少,查询执行的速度就越快。 因为您首先在内部查询中进行分组,所以您将摆脱外部查询不再需要处理的大量数据。
SQL optimisation应该回答你的一些问题。但要记住的最重要的事情是,您可以在查询的早期消除的内容越多,查询运行的速度就越快。
还有一部分数据库尝试不同的方式来运行查询。这部分服务器大部分时间都会选择最快的路径,但在查询中更具体,可以真正帮助它。 有关此页面的更多信息,请访问:Readings In Database Systems
看看你的解释,看起来这么多行的文件输出可能会对查询产生很大影响。因为主查询中的行(第二个查询的外部作用域)将使用内存表。
答案 1 :(得分:1)
在第一种情况下,索引用于查找匹配的记录,但不能用于排序,因为您不在组/ order by子句中包含最左侧的列。我有兴趣看到两个查询配置文件:
设置profiling = 1;
运行查询1;
运行查询2;
显示查询1的个人资料;
显示查询2的个人资料;
答案 2 :(得分:0)
****编辑:不好回答,因为我没有看到那里的部分。
我认为只是在第二个查询中,MySQL正在使用索引而第一个则不是。
如果你创建一个像(b, c, metric)
这样的索引,我很确定第一个查询会比第二个查询更快。
编辑得更详细:
首先查询:
第二次查询:
答案 3 :(得分:0)
出于好奇,你能试试这个版本吗?:
SELECT b, c, SUM(metric) metric
FROM aggregates
WHERE a = 'some-value'
GROUP BY b, c
和这一个:
SELECT b, c, metric
FROM (
SELECT a, b, c, SUM(metric) metric
FROM aggregates
WHERE a = 'some-value'
GROUP BY a, b, c
) t
ORDER BY b, c
和此:
SELECT b, c, SUM(metric) metric
FROM aggregates
WHERE a = 'some-value'
GROUP BY a, b, c