两个查询比一个快?

时间:2011-09-26 14:03:31

标签: mysql performance optimization

我有一个包含列的表:

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        |
+----+-------------+------------+-------+---------------+------+---------+------+--------+---------------------------------+

这是为什么?如果我在一个单独的外部查询中进行分组,而不是只在一个中进行分组,为什么它会更快?

4 个答案:

答案 0 :(得分:2)

SQL的工作方式是每个步骤的数据越少,查询执行的速度就越快。 因为您首先在内部查询中进行分组,所以您将摆脱外部查询不再需要处理的大量数据。

SQL optimisation应该回答你的一些问题。但要记住的最重要的事情是,您可以在查询的早期消除的内容越多,查询运行的速度就越快。

还有一部分数据库尝试不同的方式来运行查询。这部分服务器大部分时间都会选择最快的路径,但在查询中更具体,可以真正帮助它。 有关此页面的更多信息,请访问:Readings In Database Systems

看看你的解释,看起来这么多行的文件输出可能会对查询产生很大影响。因为主查询中的行(第二个查询的外部作用域)将使用内存表。

答案 1 :(得分:1)

在第一种情况下,索引用于查找匹配的记录,但不能用于排序,因为您不在组/ order by子句中包含最左侧的列。我有兴趣看到两个查询配置文件:

  

设置profiling = 1;

     

运行查询1;

     

运行查询2;

     

显示查询1的个人资料;

     

显示查询2的个人资料;

答案 2 :(得分: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

答案 3 :(得分:0)

****编辑:不好回答,因为我没有看到那里的部分。

我认为只是在第二个查询中,MySQL正在使用索引而第一个则不是。 如果你创建一个像(b, c, metric)这样的索引,我很确定第一个查询会比第二个查询更快。

编辑得更详细:

首先查询:

  • 执行查询没有好的索引。
  • 测试索引在(a,b,c,metric)上,你需要(b,c)上的索引((b,c,metric)也会很好)
  • 也许MySQL正在使用测试索引,但它不是一个好的索引,所以就像完全扫描表一样。

第二次查询:

  • 正在使用索引(a,b,c)
  • 在第二个实例上执行非索引查询但数据少于第一个查询。