日期:2014-05-17  浏览次数:20483 次

今天发现这个语句,这样写超慢
今天发现这个语句,这样写超慢。


ta 表rq,id 有组合索引,rq过滤后,剩下400万数据
tb 表rq 有索引,过滤后剩下1万

ta: 2亿
tb:400万

delete ta from ta a,tb where a.id=b.id and a.rq=b.rq and b.rq>'20130101' 


你们看怎么写,呵呵。


你们觉得怎么写,比较有用

------解决方案--------------------
把tb的表加载过来再关联
------解决方案--------------------
引用:
非要写成这样
select b.id,b.rq
into #tmp
from ta a,tb where a.id=b.id and a.rq=b.rq and b.rq>'20130101' 

delete ta  from ta a,#tmp b
 where a.id=b.id and a.rq=b.rq  

原先的语句,优化器会总选择先把ta表过滤rq条件,然后再连接2表,导致很慢
现在用了#,就会先过滤tb的rq,
删除时候,#走表扫描,ta 走rq,id索引。

分布式在查询效率上我觉得还是存在很大问题,你试试把远程表复制为本地表,结果可能就完全不一样了
------解决方案--------------------
一次删除400万,肯定慢(必定是表扫描)
你分N次,每次删除1000甚至500条,是正道
------解决方案--------------------
数据这么多,怎么写 SQL 都是慢的。
------解决方案--------------------
引用:
非要写成这样
select b.id,b.rq
into #tmp
from ta a,tb where a.id=b.id and a.rq=b.rq and b.rq>'20130101' 

delete ta  from ta a,#tmp b
 where a.id=b.id and a.rq=b.rq  

原先的语句,优化器会总选择先把ta表过滤rq条件,然后再连接2表,导致很慢
现在用了#,就会先过滤tb的rq,
删除时候,#走表扫描,ta 走rq,id索引。

delete ta from ta a,tb where a.id=b.id and a.rq=b.rq and b.rq>'20130101' 
你试着把from 表的顺序和where条件的顺序调调会不会起点作用?

------解决方案--------------------
还是加载过来操作比较实际
------解决方案--------------------
delete ta from ta a,(select id,r from tb where rq>'20130101') as b  where a.id=b.id and a.rq=b.rq
------解决方案--------------------
如果一定要用分布式查询的话,把查询和删除分开,先用SELECT WITH(NOLOCK)把需要删除的主键值插入临时表,再关联临时表删除

如果是我就先用bcp把那两列导过来再关联。
------解决方案--------------------
数据量大是个问题。
------解决方案--------------------
要删除很多数据,总是会比较慢,而且很容易导致阻塞,最好的办法是如果可以的话,采用分区表,按rq字段分区,这样可以直接truncate分区。

看了你的语句,能不能把那个rq的查询条件,进行分批,比如当输入'20130101',能不能写个循环,比如:一次删除1个月的数据,不过这样有可能会导致delete速度更慢,不过应该能减小阻塞。
------解决方案--------------------
试试delete top()吧
------解决方案--------------------
delete ta from ta a,(select id,r from tb where rq>'20130101') as b  where a.id=b.id and a.rq=b.rq

或者用
delete ta from ta as a where exists(select 1 from tb where rq>'20130101' and id=a.id and rq=a.rq)

会不会好点呢。
------解决方案-----