带有Left Join的Mysql查询太慢了

Posted

技术标签:

【中文标题】带有Left Join的Mysql查询太慢了【英文标题】:Mysql query with Left Join is too very slow 【发布时间】: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 列都应该有索引 【参考方案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.ididtbl_rlsr 其中r.id 不在(从tblc_comment_manager 中选择不同的cm.rlsc_id 作为cm

【讨论】:

以上是关于带有Left Join的Mysql查询太慢了的主要内容,如果未能解决你的问题,请参考以下文章

MySQL UNION ALL 太慢了

带有 SUM 的 MySQL LEFT JOIN 很慢

PostgreSQL join 获取表中的所有行,太慢了

SqlDataAdapter.Fill 即使是一条记录也太慢了

MySql 之 left join 查询结果

带有子查询语法的 LEFT OUTER JOIN