【问题标题】:Query takes too much time with JOIN使用 JOIN 查询花费了太多时间
【发布时间】:2013-09-16 08:09:32
【问题描述】:

我需要一些帮助来提高以下查询性能

SELECT * 
FROM   dle_pause 
       LEFT JOIN dle_post_plus 
              ON ( dle_pause.pause_postid = dle_post_plus.puuid ) 
       LEFT JOIN dle_post 
              ON ( dle_post_plus.news_id = dle_post.id ) 
       LEFT JOIN dle_playerfiles 
              ON ( dle_post.id = dle_playerfiles.post_id ) 
WHERE  pause_user = '2'; 

它需要3 rows in set (0.35 sec) 问题在于第三个连接。其中一行没有dle_post.id = dle_playerfiles.post_id,因此它会扫描整个表。

看起来我有所有需要的索引

+----+-------------+-----------------+--------+----------------------------------+---------+---------+-----------------------------------+--------+------------------------------------------------+
| id | select_type | table           | type   | possible_keys                    | key     | key_len | ref                               | rows   | Extra                                          |
+----+-------------+-----------------+--------+----------------------------------+---------+---------+-----------------------------------+--------+------------------------------------------------+
|  1 | SIMPLE      | dle_pause       | ALL    | pause_user                       | NULL    | NULL    | NULL                              |      3 | Using where                                    |
|  1 | SIMPLE      | dle_post_plus   | ref    | puuid                            | puuid   | 36      | func                              |      1 | Using where                                    |
|  1 | SIMPLE      | dle_post        | eq_ref | PRIMARY                          | PRIMARY | 4       | online_test.dle_post_plus.news_id |      1 | NULL                                           |
|  1 | SIMPLE      | dle_playerFiles | ALL    | ix_dle_playerFiles__post_id_type | NULL    | NULL    | NULL                              | 131454 | Range checked for each record (index map: 0x2) |
+----+-------------+-----------------+--------+----------------------------------+---------+---------+-----------------------------------+--------+------------------------------------------------+

【问题讨论】:

  • 你有关于 dle_pause.pause_postid 和 dle_playerfiles.post_id 的索引吗?您必须摆脱 EXPLAIN 查询中的 ALL 类型。这意味着完成了全表扫描,这就是它变慢的原因。

标签: mysql performance join


【解决方案1】:

如果您没有在 dle_playerfiles 的 post_id 上放置索引,则在其上放置索引。
如果您已经在其上放置了索引,那么在最后加入的查询中写入“使用索引”,如下所示:

 SELECT * 
  FROM 
     dle_pause 
   LEFT JOIN dle_post_plus 
          ON ( dle_pause.pause_postid = dle_post_plus.puuid ) 
   LEFT JOIN dle_post 
          ON ( dle_post_plus.news_id = dle_post.id ) 
   LEFT JOIN dle_playerfiles **use index(post_id)**
          ON ( dle_post.id = dle_playerfiles.post_id ) 
   WHERE 
     pause_user = '2';

这也将使用第四个表的索引。现在你的解释表明它没有在第四个表上使用任何索引,因此扫描了 131454 行。

【讨论】:

  • 就我而言,这是一个非常糟糕的错误。我没有在两个表中都使用 int 类型的 post.id 列,而是在其中一个表中使用了 varchar!
  • 通过这个新查询,您是否完成了“解释”?在解释键列是否显示第四个表的索引的结果中,现在在 rows 列中扫描了多少行?
【解决方案2】:

我可以提出两种解决方案。

第一种选择:

为您与 LEFT 连接比较的键创建一个仅包含非 NULL 值的临时表。

类似这样的:

select *
into #dle_post_plus 
where pause_postid is not null

对所有三个表都这样做。

然后在不包含 NULL 值的临时表上使用您的原始查询。

第二种选择: 为您在左连接中比较的每个键创建一个索引,这样索引将为您完成这项工作。

当然,你总是可以结合我建议的两种方法。

【讨论】:

    猜你喜欢
    • 2013-07-11
    • 2018-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-04
    • 2012-06-04
    • 1970-01-01
    相关资源
    最近更新 更多