INNER JOIN导致查询执行时间很长

时间:2014-05-19 11:59:50

标签: mysql sql query-optimization

我有数百万条记录的大桌子。下面的查询仅执行0.2秒,这很好。

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条记录时完成
  4. 在第二种情况下,我认为会发生这种情况:

    1. 使用索引经验的订单
    2. 加入数百万行中的每一条记录< - slow
    3. 适用WHERE
    4. 找到100条记录时完成
    5. 您有什么建议我如何优化它?

      修改:探索快速和慢速查询:

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

3 个答案:

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

如果您仍在努力(表现性能),请为上述内容提供一个EXPLAIN以及所有相关表格的正确DDLS。

答案 1 :(得分:0)

将第一个阶段作为JOIN连接到子查询,然后加入更新表: -

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

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