【问题标题】:Mysql query with Left Join is too very slow带有Left Join的Mysql查询太慢了
【发布时间】:2011-03-16 12:20:40
【问题描述】:

查询:

   select `r`.`id` as `id` 
     from `tbl_rls` as `r` 
left join `tblc_comment_manager` as `cm` on `cm`.`rlsc_id` != `r`.`id`

两个表都有 8k 条记录,但为什么速度很慢,有时需要 2-3 分钟甚至更长时间?

OMG,这个查询使 mysql 服务器停机。稍后会回复你们:(

所有建议索引列的人都是正确的。 是的,我写的查询是愚蠢和错误的。谢谢指正。

【问题讨论】:

  • 有索引吗?如果有,在哪几列?
  • id 列都应该有索引

标签: sql mysql join query-optimization


【解决方案1】:

考虑同时索引​​您的表。我们在超过 100 万条记录的表上运行多个左连接,返回结果不会超过一两秒。

【讨论】:

  • 天哪,这就是罪魁祸首。我从 10 分钟缩短到 0.9 毫秒。有关 MySQL 分析工具的任何建议,可以告诉您应该在数据库中使用哪些索引?
  • 索引成功了。查询现在在 233 毫秒内运行,以前是 48 秒
【解决方案2】:

您真的需要!= 还是应该是=

 select `r`.`id` as `id` from `tbl_rls` as `r` 
  left join `tblc_comment_manager` as `cm` 
on  `cm`.`rlsc_id`!=`r`.`id

这将选择几乎 2 个表的笛卡尔积。 (我猜大约有 6000 万行)

编辑:来自评论

是的,它是“!=”来匹配 tbl_rls.id 那些不在 tblc_comment_manager 中

如果您想使用outer join 方法,我认为这就是您所需要的。

 select DISTINCT `r`.`id` as `id` from `tbl_rls` as `r` 
  left join `tblc_comment_manager` as `cm` 
on  `cm`.`rlsc_id`=`r`.`id
WHERE `cm`.`rlsc_id` IS NULL

虽然我的偏好通常是

 select `r`.`id` as `id` 
 from `tbl_rls`
 as `r` 
 WHERE NOT EXISTS(
          SELECT * FROM `tblc_comment_manager` as `cm` 
          WHERE  `cm`.`rlsc_id`=`r`.`id)

【讨论】:

  • 是的,它是“!=”来匹配tbl_rls.id那些不在tblc_comment_manager中的@
【解决方案3】:

你要选择什么?

如果您想查找在其他表中没有匹配记录的 tbl_rls 记录,请使用此查询

select `r`.`id`
from `tbl_rls` as `r` 
left join `tblc_comment_manager` as `cm` 
    on  `cm`.`rlsc_id`=`r`.`id
where `cm`.`rlsc_id` IS NULL

【讨论】:

    【解决方案4】:

    MySQL 的EXPLAIN 可能会帮助您了解发生了什么。

    【讨论】:

    • 这个感觉应该是评论
    【解决方案5】:

    您可能需要提供更多信息。但我会尝试的一件事是颠倒你的 ON 子句的顺序(因为它很容易):

    ON r.id != cm.rlsc_id

    编辑:你应该在你的 PK (id) 列上放置索引。

    但我认为this article might help you out

    基本上它说NOT INLEFT JOIN 占用更少的资源。该文章中的评论者提到使用NOT EXISTS 是最好的。

    另外,我不确定这是否准确,但this article says that NOT IN does a full table scan, and NOT EXISTS can use an index

    【讨论】:

    • @JohnB For SQL Server 'NOT IN' 和 NOT EXISTS 效率更高(尽管必须注意第一个的 NULL)。对于 MySQL,我不确定建议是什么。
    • 另外,还有人指出了做法:WHERE cm.rlsc_id IS NULL
    • @Martin:读过高性能 MySQL 的人可能知道答案 - amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
    • 尽管如此,他有几个选项需要 5 分钟来测试。 Arsheep,请发布您的结果!
    • @Martin:当您在 MySQL 中将列设置为 PK 时,它会自动为该列创建索引吗?如果没有,请为您的 PK 列 Arsheep 创建索引!
    【解决方案6】:

    看起来您想要不在 tblc_comment_manager 表中的 r.id 值。

    使用不在

    选择r.idid
    tbl_rlsr
    其中r.id 不在(从tblc_comment_manager 中选择不同的cm.rlsc_id 作为cm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      相关资源
      最近更新 更多