带有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 IN
比LEFT 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
.id
为id
从tbl_rls
到r
其中r
.id
不在(从tblc_comment_manager
中选择不同的cm
.rlsc_id
作为cm
)
【讨论】:
以上是关于带有Left Join的Mysql查询太慢了的主要内容,如果未能解决你的问题,请参考以下文章