使用Left Join的Mysql查询速度非常慢

17

查询:

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

这两个表格都有8千条记录,但为什么查询非常慢,需要2-3分钟或更长时间?

天啊,这个查询会让MySQL服务器崩溃。我马上回复你们 :(

所有建议对列进行索引的人都是正确的。是的,我写的查询很傻,有错误。谢谢纠正。


1
有索引吗?如果有,它们是在哪些列上? - middus
1
两个 id 列都应该有索引。 - JohnB
6个回答

27

考虑对表进行索引。我们在一个超过一百万条记录的表上运行多个左连接时,返回结果不需要花费超过一两秒的时间。


1
这真是个大问题啊。我从10分钟降到了0.9毫秒。你有没有什么推荐的MySQL分析工具,可以告诉你应该在数据库上使用哪些索引? - Joshua Pinter
索引起了作用。查询现在只需要233毫秒,之前是48秒。 - Kxng Kombian

13
你真的需要使用 != 吗?或者原本应该使用 =
 select `r`.`id` as `id` from `tbl_rls` as `r` 
  left join `tblc_comment_manager` as `cm` 
on  `cm`.`rlsc_id`!=`r`.`id

这将选择两个表的近似笛卡尔积。(我猜大约有6000万行)

编辑:来自评论

是的,可以使用 " != " 来匹配 tbl_rls.id 那些不在 tblc_comment_manager 中

如果您想使用外连接方法,我认为这是您需要的。

 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中的。 - Arshdeep

4

你想选择什么?

如果您想查找在其他表中没有匹配记录的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
这感觉应该是一条评论。 - treyBake

3
您可能需要提供更多信息。但是我建议您尝试颠倒ON子句的顺序(因为这很容易):ON r.id != cm.rlsc_id。并且您应该在PK(id)列上放置索引。但我认为这篇文章可以帮助您:基本上它说“NOT IN”比“LEFT JOIN”使用更少的资源。该文章中的一位评论者提到,使用“NOT EXISTS”是最好的选择。此外,我不确定这是否准确,但这篇文章说,“NOT IN”会进行全表扫描,而“NOT EXISTS”可以使用索引。

1
@JohnB 对于 SQL Server,'NOT IN' 和 NOT EXISTS 更加高效(尽管对于第一个语句需要注意 NULL 值)。对于 MySQL,我不确定建议是什么。 - Martin Smith
@Martin:读过《高性能MySQL》的人可能知道答案 - http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064 - JohnB
@Martin:当你在MySQL中将一列设置为PK时,它是否会自动为该列创建索引?如果没有,请为您的PK列创建索引,Arsheep! - JohnB
@JohnB - 是的,我这边进行了快速测试,似乎表明您将自动获得主键索引,但我猜这可能对“tblc_comment_manager”没有帮助。 - Martin Smith
@Martin Smith:这取决于列是否为可空非空 - OMG Ponies
显示剩余2条评论

1

看起来你想要 tblc_comment_manager 表中没有的 r.id 值。

使用 Not In

select r.id as id
from tbl_rls as r
where r.id not in (select distinct cm.rlsc_id from tblc_comment_manager as cm)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接