2014-05-19 43 views
2

我有相当大的表和数百万条记录。下面的查询在0.2s内执行,这很好。INNER JOIN导致查询执行时间很长

SELECT ch1.* 
FROM citizens_history ch1 
WHERE ch1.update_id_to = ( 
    SELECT MAX(ch2.update_id_to) 
    FROM citizens_history ch2 
    WHERE ch2.id = ch1.id 
) 
ORDER BY ch1.experience DESC 
LIMIT 100 

然而,当我试图添加INNER JOIN,这样

SELECT ch1.*, upd.* 
FROM citizens_history ch1 
INNER JOIN updates upd ON upd.id = ch1.update_id_to 
WHERE ch1.update_id_to = ( 
    SELECT MAX(ch2.update_id_to) 
    FROM citizens_history ch2 
    WHERE ch2.id = ch1.id 
) 
ORDER BY ch1.experience DESC 
LIMIT 100 

它永远执行。在第一种情况下,我认为MySQL是这样:

  1. 订单利用指数
  2. 适用WHERE
  3. 涂饰时,有100条记录

在第二种情况下的经验,我认为这种情况发生:

  1. 订单使用体验指数
  2. 加入为每一个记录了数百万行<的 - 慢
  3. 适用WHERE
  4. 完成时有100条记录

你有任何建议如何优化呢?

编辑:EXPLAIN快速和慢速查询:

+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 
| id | select_type  | table | type | possible_keys | key  | key_len | ref     | rows | Extra  | 
+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 
| 1 | PRIMARY   | ch1 | index | NULL   | experience | 3  | NULL   | 100 | Using where | 
| 2 | DEPENDENT SUBQUERY | ch2 | ref | id   | id   | 3  | db.ch1.id | 1 | Using index | 
+----+--------------------+-------+-------+---------------+------------+---------+--------------+------+-------------+ 

+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
| id | select_type  | table | type | possible_keys      | key  | key_len | ref   | rows | Extra          | 
+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
| 1 | PRIMARY   | upd | index | PRIMARY        | datetime | 5  | NULL   | 389 | Using index; Using temporary; Using filesort | 
| 1 | PRIMARY   | ch1 | ref | PRIMARY,update_id_to,update_id_to_2 | PRIMARY | 4  | db.upd.id | 112 | Using where         | 
| 2 | DEPENDENT SUBQUERY | ch2 | ref | id         | id  | 3  | db.ch1.id | 1 | Using index         | 
+----+--------------------+-------+-------+-------------------------------------+----------+---------+--------------+------+----------------------------------------------+ 
+1

你可以做的第一个查询中子查询,然后再进行加入? –

+0

我需要在我的应用程序的代码中做很多更改。将主查询放入子查询中是否可行? – stil

+4

好吧,我们假设,在Explain前面添加查询并查看查询计划是什么。我预计最大的打击将是我自己的排序。可能性的数量,但没有执行计划我甚至无法正确猜测 –

回答

2

重写第一个查询,如下所示,然后根据需要修改......

SELECT ch1.* 
    FROM citizens_history ch1 
    JOIN 
    (SELECT id 
      , MAX(update_id_to) max_update_id_to 
     FROM citizens_history 
     GROUP 
      BY id 
    ) ch2 
    ON ch2.id = ch1.id 
    AND ch2.max_update_id_to = ch1.update_id_to 
ORDER 
    BY ch1.experience DESC 
LIMIT 100 

如果你还在苦苦挣扎(performancewise),为上述内容提供一个解释以及所有相关表的正确DDLS。

0

执行第一阶段为连接到一个子查询,然后加入上的更新表: -

SELECT ch1.*, upd.* 
FROM citizens_history ch1 
INNER JOIN 
(
    SELECT id, MAX(update_id_to) AS max_update_id_to 
    FROM citizens_history 
    GROUP BY id 
) ch2 ON ch1.id = ch2.id AND ch1.update_id_to = ch2.max_update_id_to 
INNER JOIN updates upd ON upd.id = ch1.update_id_to 
ORDER BY ch1.experience DESC 
LIMIT 100 
0

你可以试试:

SELECT ch1.* 
    FROM citizens_history ch1 
    LEFT JOIN citizens_history ch2 
    ON ch2.id = ch1.id 
    AND ch1.max_update_id_to > ch2.update_id_to 
    WHERE ch1.max_update_id_to is null 
    ORDER BY ch1.experience DESC 
    LIMIT 100