请求执行时间太长

时间:2014-07-02 09:42:15

标签: mysql sql optimization

我正在寻找一些建议或优化。 表定义:

CREATE TABLE IF NOT EXISTS MilestonesAndFlags(
    id SERIAL,
    site_id BIGINT,
    milestone BIGINT,
    value BIGINT,
    TIMESTAMP BIGINT,
    timestamp_confirmation BIGINT,
    COMMENT TEXT,
    INDEX(site_id),
    INDEX(milestone),
    INDEX(milestone,site_id)
);

在此表中,我存储了每个不同站点的时间戳(以便能够对任何更改进行历史视图)的不同里程碑。表当时有大约一百万行。

当我尝试使用

等查询获取每个网站的最新实际里程碑值时,会出现问题
SELECT site_id,
       value
FROM SitesMilestonesAndFlags
WHERE id IN
        (SELECT max(id)
         FROM SitesMilestonesAndFlags
         WHERE milestone=1
         GROUP BY milestone,
                  site_id);

此请求执行时间在我的电脑上高出5分钟.. EXPLAIN似乎没问题:

+----+--------------------+--------------------+------+-----------------------+-------------+---------+-------+--------+--------------------------+
| id | select_type        | table              | type | possible_keys         | key         | key_len | ref   | rows   | Extra                    |
+----+--------------------+--------------------+------+-----------------------+-------------+---------+-------+--------+--------------------------+
|  1 | PRIMARY            | MilestonesAndFlags | ALL  | NULL                  | NULL        | NULL    | NULL  | 1111320| Using where              |
|  2 | DEPENDENT SUBQUERY | MilestonesAndFlags | ref  | milestone,milestone_2 | milestone_2 | 9       | const |  180660| Using where; Using index |
+----+--------------------+--------------------+------+-----------------------+-------------+---------+-------+--------+--------------------------+

有关更正确的查询或表结构的任何建议吗? MySQL> = 5.5

1 个答案:

答案 0 :(得分:1)

我会采取行动并建议您使用temporary aliased table而不是dependent subquery的where语句。不确定mysql是否已优化或为主/外查询的每一行运行子查询。

如果您对大数据量运行查询并返回结果,那将非常有趣。

实施例

SELECT *
FROM MilestonesAndFlags AS MF,

  (SELECT max(id) AS id
   FROM MilestonesAndFlags
   WHERE milestone=1
   GROUP BY milestone,
            site_id) AS MaxMF
WHERE MaxMF.id = MF.id;

SQLFiddle:http://sqlfiddle.com/#!2/a0d628/10

优点和缺点:

<强>临 避免依赖子查询。

<强>缺点:

  • 加入导致投影和选择。这会导致临时表的所有行与原始表的行“相乘”,然后在条件过滤器的位置。

更新

我还怀疑mysql的版本在优化过程中扮演了重要角色。 下面是2个不同mysql版本的解释结果,其中一个将子查询定义为依赖,另一个定义为非。

MySQL 5.5.32

ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     MilestonesAndFlags  ALL     (null)  (null)  (null)  (null)  29  Using where; Using filesort
2   DEPENDENT SUBQUERY  MilestonesAndFlags  ref     milestone,milestone_2   milestone_2     9   const   15  Using where; Using index

http://sqlfiddle.com/#!2/a0d628/11

MySQL MySQL 5.6.6 m9

ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     MilestonesAndFlags  ALL     (null)  (null)  (null)  (null)  29  Using where; Using filesort
2   SUBQUERY    MilestonesAndFlags  ref     milestone,milestone_2   milestone_2     9   const   15  Using where; Using index

http://sqlfiddle.com/#!9/a0d62/2