代码改变世界

游标性能千倍之差

2010-09-28 09:41  greg_echo  阅读(634)  评论(3)    收藏  举报

前几天写了一个存储过程,用于处理失败记录,处理流程大体为:

 

注1:从总数据表Tb_All中每次取一条数据与Tb_Fail中的数据进行比对,查看该记录成功还是失败,如果过失败则从表Tb_All中删除该记录,成功则保留该记录。

注2:Tb_Fail表中不止包含Tb_All表的记录还包括其它表记录。

注3:Tb_All数据量200万,Tb_Fail数据量20万。

  

处理方法一:

         在一开始的处理方法中并没有对性能考虑太多,随手用了数据库游标,一条一条取记录然后比对记录,进行操作。

代码如下:

   

--循环表
 declare @count int
 select @count=count(*) from Tb_All
 if (@count>0)
 begin 
        declare @mobile varchar(21)
		DECLARE table_cur CURSOR FOR
		SELECT mobile FROM Tb_All 

		OPEN table_cur
		FETCH NEXT FROM table_cur INTO @mobile

		WHILE @@fetch_status = 0

		BEGIN
		 --减少数据

				  if exists(select * from tb_Fail where msisdn=@mobile)

				  begin 

					delete from tb_UserScheme  where us_msisdn=@mobile
						
				  end
			end
			FETCH NEXT FROM table_cur INTO @mobile
		END
		DEALLOCATE table_cur
 end

 

等写完存储过程进行测试时,才恍然大悟,性能极为低下,每条记录都是平均10万次查询,整个表记录查询完大约要进行千亿次操作。而且从执行时间看也的确如此,大约跑了3个小时还没有跑完,实在看不下去了,就给停了。

 

处理方法二:

使用连接表的方式进行查询:

代码如下:

 

 --循环表
 declare @count int
 select @count=count(*) from tb_All
 if (@count>0)
 begin 
			  
				

if exists(select tb_Fail.msisdn from tb_All,tb_Fail where msisdn=tb_All.mobile)

	begin 

			

	delete tb_All from tb_Fail  where tb_Fail.msisdn=tb_All.mobile
					

	end
			
 end

 

写完执行,耗时13秒,搞定。

 

此文亦水,只是给大家一个更直观的对比游标的性能的例子,希望大家多拍砖!