两张表的字段完全一样,一张是临时表,一张是正式表,现在需要做的是,先把临时表里id和正式表里id相同的列全部更新到正式表,update A set A.1 = A.1+B.1,A.2 = A.2+B.2,... from B where A.id=B.id
然后再把临时表里这些数据删除掉,剩下的就全部insert into到正式表,然后清空临时表,这个存储过程是一直循环执行的,而且还有好几个类似这样的存储过程,
现在我的问题是,当临时表的数据量大于2W的时候,执行这个存储过程相当耗时,造成数据库的阻塞,完全接受不了,所以请教大家帮忙优化一下,或者能给一个更好的思路,不胜感激、、、、、、
然后再把临时表里这些数据删除掉,剩下的就全部insert into到正式表,然后清空临时表,这个存储过程是一直循环执行的,而且还有好几个类似这样的存储过程,
现在我的问题是,当临时表的数据量大于2W的时候,执行这个存储过程相当耗时,造成数据库的阻塞,完全接受不了,所以请教大家帮忙优化一下,或者能给一个更好的思路,不胜感激、、、、、、
解决方案 »
- 本月余额=上月余额+本月预留
- 把有100多个表的数据库的数据清空后,数据文件还是很大,如何变小?
- 关于oracle的分页查询
- WM6上的SQLCE数据库,有支持批处理执行SQL语句的方法嘛?
- 急急急 SQL数据库,老是提示错误, (getdate()、'nopicture.gif' 大部分是这两个,大虾门帮忙看下撒
- 执行存储过程错误,求助
- 请帮写一条SQL语句,能把我的数据修正过来【在线等待】
- 请教高手。。。
- sql server 的最大连接数能达多少。几千人通过asp页面同时访问,如何提高效率!
- 触发器脚本中我如何得到当前插入的记录各字段值?
- 非域下采用证书配置数据库镜像问题,配置不到见证服务器
- 为什么这样定义的游标是只读?
2 insert 到正式表
3 update 到正式表
没有条件.
这是比较严格一点的, 如果这样的很多, 可以再把值设置高一些
ID都是主键,两个表也都有索引,正式表是唯一索引,临时表不唯一;
你说的是先insert后,剩下的就直接更新,没有条件了?没太明白,没条件是什么意思?就算临时表里只剩下更新的数据,那也得有个where A.id=B.id才行吧?
delete也是很耗时的。
MSSQL 2008支持merge into
恩,之所有要建个临时表,就是想实现批量操作,之前我的做法是来一条数据就直接update,结果因为数据量很大,造成数据库一直死锁,现在我想的是加个临时表,中间过渡一下,反正最终目就是要更新到正式表
update 还是需要条件
临时表做索引没,分析下是update关联慢,还是insert 慢,最好有执行计划展示出来
r.command,
r.blocking_session_id, --阻塞当前会话的会话id
r.wait_type, --等待类型
r.wait_time, --等待时间
r.last_wait_type, --最后等待类型
r.wait_resource,
r.open_transaction_count --打开事务数
from sys.dm_exec_requests r
where @@SPID = 会话id
r.command,
r.blocking_session_id, --阻塞当前会话的会话id
r.wait_type, --等待类型
r.wait_time, --等待时间
r.last_wait_type, --最后等待类型
r.wait_resource,
r.open_transaction_count --打开事务数
from sys.dm_exec_requests r
where r.session_id = 调用存储过程的会话id
如果非要加快它,需要提升硬件方面的内容,比如说做表分区,
映射到几个不同的磁盘,分摊IO的开销,但是这个分区函数你不好找
为什么不将正式表A和临时表B 的数据查询出来insert 第三者表C中呢?
...
commit tran看不代码,我只能提供这些信息了。
where exists (select 1 from B where A.id=B.id)insert into A select * from B 然后删除表数据,删除表,这个会吧可以中间提交一次以减少缓冲空间的使用。
可能是存儲過程寫法有問題,可採用分批提交,特別是10W以上都需要考慮分批提交數據,可參考:
use tempdb
go
--創建測試表
if object_id('Tb_A') is not null drop table Tb_A
if object_id('Tb_B') is not null drop table Tb_Bcreate table Tb_A(ID int primary key ,c2 nvarchar(50),c3 nvarchar(50)) --ID作為主鍵
create table Tb_B(ID int primary key ,c2 nvarchar(50),c3 nvarchar(50)) --ID作為主鍵
go--批量處理使用該字段控制;
alter table Tb_B add Col_Identity int identity(1,1)
go--插入測試數據
set nocount on
insert into Tb_A(ID,c2,c3) values(1,'c1','c2'),(2,'c3','c4'),(3,'c5','c6')
insert into Tb_B(ID,c2,c3) values(2,'c3_a','c4_a'),(3,'c5_b','c6_b'),(4,'c7','c8')
set nocount offgo-- 存儲過程內容:
if object_id('up_MoveData_BtoA') is not null drop proc up_MoveData_BtoA
go
create proc up_MoveData_BtoA
Asdeclare @batch int=2000, --每2000行提交一次,可以根據實際服務器來調整
@For int=1
While 1=1
beginif Not Exists(select 1 from dbo.Tb_B) break;Begin Try
Begin Transaction
update a
set a.c2=b.c2,a.c3=b.c3
from Tb_A a
inner join Tb_B b on b.ID=a.ID
and b.Col_Identity between (@For-1)*@batch+1 And @For*@batch
insert into dbo.Tb_A ( ID, c2, c3 )
select ID,c2,c3 from dbo.Tb_B a where not exists(select 1 from dbo.Tb_A y where y.ID=a.ID) and a.Col_Identity between (@For-1)*@batch+1 And @For*@batch
delete Tb_B where Col_Identity between (@For-1)*@batch+1 And @For*@batch
set @For+=1;
Commit Transaction
End Try
Begin Catch
Declare @Error nvarchar(2047)
Set @Error=Error_message()
Raiserror 50001 @Error
Rollback Transaction
goto ExitFlag
End Catch
end
ExitFlag:
go
--調用存儲過程:
exec up_MoveData_BtoA
go