优秀的编程知识分享平台

网站首页 > 技术文章 正文

Oracle=>Sqlserver迁移:Sqlserver内存溢出的问...

nanyue 2024-08-02 17:47:13 技术文章 9 ℃

因为项目的升级,数据库从oracle改到了sqlserver,这样带来的问题是需要做个移行工具,将Oracle的数据移植到Sqlserver,按照一般的想法,在sqlserver端建一个dblink,连接oracle,insert...select的方式进行数据插入,就解决了,但是事情没有那么简单,接下来将实现过程中遇到的问题,以及如何排雷,最终完美实现的过程说明下,我想对有这方面需求的朋友,一定有所帮助

背景:

小数据量的表,图形化的移行工具,不适合复杂的工厂环境,不在讨论范围。

网上能看到的案是修改max server memory的值,都没法解决。另外修改max server memory的值需要重启SQLSERVER服务,实际的客户现场是不可能这么实现。

我们讨论大数据量表移行,有一个操作log表,数据600多万件,占内存3G多,从oracle中将操作log表中的数据,导入到Sqlserver的操作log表。服务器内存16G。

在Oracle数据库之间,600万件数据的插入是没有问题的,但是往Sqlserver插入,就会出现内存溢出。

案1:创建dblink,dblink..表名的方式访问

INSERT SqlServer表 Select * from OracleLink..LDBTLOGT 16G内存,处理了30万件时内存超了,现象就是内存一直增长,在剩余内存不多时,它会自动回收几次,但是最终还是会内存溢出

案2:dblink..表名的方式访问,每次插入件数指定

使用sqlserver offset,每1000件取一次,进行插入,没有改善,内存还是一直增长。原因在案3说明

案3:使用OPENQUERY代替OracleLink..的DBLink的使用方法

INSERT Sqlserver表 SELECT * FROM OPENQUERY(OracleLink,'select * from Oracle表)

OracleLink是dblink ,内存还是一直增长。

※这里说明下,为什么使用OPENQUERY代替OracleLink..,通过执行计划大家可以看到区别

使用OPENQUERY和OracleLink..的区别,OPENQUERY是直接连接远程的oracle数据库,OracleLink..是从oracle取回来,本地过滤,所以指定件数不起作用

案4:使用OPENQUERY,同时通过oracle的rownum对数据范围进行分割,每处理一次,内存能够释放,600万处理后,内存回收正常

INSERT INTO LDBTLOGT ( SELECT * FROM OPENQUERY(OracleLink,'select Oracle字段 FROM (SELECT Oracle字段,rownum num FROM LDBTLOGT) t2 WHERE t2.num between $BEGINNUM and $ENDNUM'))

总结

为什么在Oracle没有问题,在Sqlsever会出现内存溢出的问题。我认为有2点原因:

1)Sqlserver的内存使用策略:

对于sqlserver数据库什么时候回收内存是系统自己来做的,我们无法来干预。并且Sqlserver的内存使用策略是最大化利用内存,也就是有多少用多少,留有余地太小了,是不是像败家子。我试过将物理内存升到32G,它还是会将内存使用到31G多,然后再释放调整,最终溢出。Sqlserver这方面和Oracle还是没法比。

2)DBLink的内部机制不同

要使用OPENQUERY的方式调用dblink,而不要使用dblink..的方式,原因上面的执行计划可以看出来,使用dblink..的方式,相当于从远程将所有的数据取到本地后,再进行件数过滤。是不是感觉这种方式就不应该存在。

通过案4,内存溢出的问题得到了解决,接下来遇到执行时间太慢的问题,请继续关注

Tags:

最近发表
标签列表