MYSQL NOT IN优化

我的sql写法:selecta.*fromrecordawherea.idnotin(selectb.rec_idfromoffline_record);数据量:reco... 我的sql写法:
select a.* from record a where a.id not in(select b.rec_id from offline_record);
数据量:record大约2w条 offline_record大约4w条
这样很慢,不知道为什么(record.id和offline_record.rec_id都建了索引的)

网上查了not in优化,进行了以下尝试:
1.select a.* from record a inner join offline_record b on a.id!=b.rec_id
2.select a.* from record a where not exists(select b.rec_id from offline_record b where b.rec_id=a.id)
1语句我知道!=这个地方应该有问题,但不知道该怎么改进,现在的写法不行,查不出来数据,
2语句查询很慢,并且查的时候过一段时间就会卡死
网上还有left join方式来对not in进行改进,我也试了 ,没用,查的时候很卡
希望给帮帮忙啦,给个解决办法我 ,万分感谢了!

PS:mysql是默认配置,没有进行配置优化,不论是配置优化的建议或sql语句优化的建议都可,也可以是算法上的改进
展开
 我来答
Wings_sysu
2012-06-15 · TA获得超过535个赞
知道答主
回答量:89
采纳率:0%
帮助的人:95.4万
展开全部
算法上存在很大问题。我们先来分析该算法的执行次数。
按照你的方法,record表中的id字段要全部查询一遍,也就是2W次查询,而每次查询,最坏

情况下需要与offline_record中的rec.id进行4W次比较,这又导致offline_record表的4W次

查询(取rec_id )。假设满足
a.* from record a where a.id not in(select b.rec_id from offline_record);
条件的记录一共有N条,那么,最坏情况下,该算法所做的查询次数为:
2W(取record.id)+2W*4W(每取一次record.id就要取一次offline_record.rec_id且offline_record的最后一条数据满足条件)+N(每

条满足条件的记录需要再在record中取该记录全部数据)
所做的比较次数为:
2W*4w

考虑最好情况下的效率,该算法所做的查询次数为:
2W(取record.id)+2W*1(每取一次record.id就要取一次offline_record.rec_id且offline_record的第一条数据满足条件)+N(N(每

条满足条件的记录需要再在record中取该记录全部数据)
所做的比较次数为:
2W*1
因此,该算法平均查询次数为:
2W+(4w*2w+1)*2w/2+N ->8*10^12
天文数字!这还不考虑将近4亿次的平均比较次数,所以你的执行效率当然低了

下面,我们对该算法来进行优化:
算法主要解决的问题是,取表record中id不等于offline_record.rec_id的数据。现假定id为record的主键(你的问题没有指明,但是你会看到无论id是否主键都不影响分析),设计算法如下:
1、取offline_record.rec_id的结果为集合,并对该集合进行排序,设最终生成的集合为A 。则,查询数据库4w次,生成集合的算法按照O(N*ln N)的效率来算平均情况下比较O(4W*ln 4w),约等于64W次,排序次数按照O(N*ln N)的效率来算平均情况下比较O(4W*ln 4w),约等于64W次。

2、顺序取record中的id与第一步生成的集合A进行比较,从而得出最终结果。该过程中由于record.id与A均为有序表,所以比较次数为2w次,查询次数为2w+N次。

如上算法,查询次数为 4W+2W+N=6W+N次,平均比较次数为 64W+64W+2W=130w次。
显而易见,该算法对原算法进行了最大的优化,大概将速度提高了10*8倍。
考虑到对数据库的查询时间远远大于排序比较时间,改进厚的算法在实际操作中还会有更好的表现。

至于你对mysql查询语句的优化,则是治标不治本之举,虽然有用,但毕竟是微小量变,不足与影响全局,在一个坏的算法下,几乎不能提升性能。
莱伯泰科
2024-09-02 广告
LabTech Group,即北京莱伯泰科仪器股份有限公司,是业界领先的实验室科学仪器与解决方案提供商。我们专注于分析测试仪器的研发、生产和销售,致力于为全球科研工作者、高校及企业实验室提供高性能、高稳定性的产品与服务。通过持续的技术创新与... 点击进入详情页
本回答由莱伯泰科提供
厍曼冬6o
2012-06-15 · TA获得超过1569个赞
知道小有建树答主
回答量:1336
采纳率:0%
帮助的人:1186万
展开全部
将两个表的已建立的索引删除,重新建立索引,然后执行以下语句
select * from record a where not exists(select 1 from offline_record where rec_id=a.id)
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
fbnc65ki
2012-06-15 · TA获得超过101个赞
知道小有建树答主
回答量:229
采纳率:0%
帮助的人:259万
展开全部
select a.*
from record a
where a.id not in(select distinct b.rec_id from offline_record);
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
libin6109
2012-06-15 · 超过17用户采纳过TA的回答
知道答主
回答量:56
采纳率:0%
帮助的人:31.7万
展开全部
如果可以的话,应该只查询你需要的字段。这样你的数据量会大大减小
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式