论坛首页 综合技术论坛

not in 怎么优化

浏览 4458 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-04-23  
在MYSQL中

A表中的一个字段fieldA,B表中的一个字段fieldB

我要查select * from A where fieldA not in (select fieldB from B)

这样查的话数据量大点就很慢了,可以用什么语句代替吗?
   发表时间:2008-04-23  
当a.fieldA与b.fieldB能join上的时候都是一一映射的时候
用以下方式

--方式一
select A.* 
from A
left join b on
    a.fieldA = b.fieldB
where b.fieldB is null


如果不是一一映射
用以下方式
--方式二
select A.* 
from A
where not exists
(
    select 1 
    from B
    where a.fieldA = b.fieldB
)


当然,not exists的方式比not in快不了多少
而且,left join 会导致对表A的全表扫描,当表A中数据很多的时候,方式一也可能不够快

也可以换一种思维,在表中添加冗余
在表A中加一个使用标识位(useFlg)
一旦表B中使用了fieldA,就把表A对应记录中的useFlg设置为1
于是就可以用以下sql

--方式三
select A.* 
from A
where useFlg = '0'
已被评为好帖!
   发表时间:2008-04-23  
谢谢,你很热心,换种思维方法是不错,可是B表中还有开始时间和结束时间两个字段,主要是要查在一段时间内fieldA not in fieldB  所以也不好用冗余
0 请登录后投票
   发表时间:2008-04-29  
armorking 写道
当a.fieldA与b.fieldB能join上的时候都是一一映射的时候
用以下方式

--方式一
select A.* 
from A
left join b on
    a.fieldA = b.fieldB
where b.fieldB is null


如果不是一一映射
用以下方式
--方式二
select A.* 
from A
where not exists
(
    select 1 
    from B
    where a.fieldA = b.fieldB
)


当然,not exists的方式比not in快不了多少
而且,left join 会导致对表A的全表扫描,当表A中数据很多的时候,方式一也可能不够快

也可以换一种思维,在表中添加冗余
在表A中加一个使用标识位(useFlg)
一旦表B中使用了fieldA,就把表A对应记录中的useFlg设置为1
于是就可以用以下sql

--方式三
select A.* 
from A
where useFlg = '0'



赞一个,思路很清晰。数据量大到一定程度(百万)非常有效。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics