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

关于数据库表导出成文本文件的性能问题
前提:目的是实现一个程序,能够实现某些表在满足某些事件的时候能够实现数据导出,生成文件(.CSV结构),然后把文件扔给下一个程序去处理.
实现方式: 使用ADO Connection 建立连接读表,将结果集赋给_Recordset(ADO DATASET) 然后通过循环读取,将值写入到带缓冲区的TFileStream(流中)
//连接字符串 
sConnectStr := 'Provider = OraOLEDB.Oracle.1;'
  + 'Persist Security Info = True;FetchSize = ' + IntToStr(iFetchSize) + ';'
  + 'Data Source = ''' + Trim(sAlias) + ''';'
  + 'User ID = ''' + Trim(sUserName) + ''';'
  + 'Password =''' + Trim(sPassword) + '''';
//结果集缓存在服务器
TConnection.CursorLocation:=adUseServer;
RS:=TConnection.Execute(Self.Fsql,varRecordCount,adOpenForwardOnly);
//建立缓冲区
RS.CacheSize := iCacheSize;
 for 循环读取记录写入到文件流中  

目前的性能如下
  数据库服务器 16CPU + 32G内存, 程序运行机器(4 CPU ,2G)内存
因为是串行操作,程序只能使用到1个CPU,(该CPU的占用率为100%),导出速率为 3.2M/S!
目前还想提高下性能,因为这是一个大公司的数据中心主动推送服务,每日推送数据量可能会在5G-10G左右!
瓶颈: 文件流写入,如果是循环写入的话,速度在个人PC上可以到10M/S,因此这块不是问题,我们怀疑应该是 ADO取结果集这块会慢,数据库是缓存在服务器上的,
服务器跟应用程序的连接(100MB),同一局域网!缓存到本地,本地机器的内存不够扛,并且缓存到本地的性能经测试跟缓存到服务器上的性能差不多多远!

当然可行的方案有很多,第一个文件导出并发操作(有4个CPU,就可以开4个线程进行导)!
ORACLE自己使用的imp/exp工具的速度非常快,在我现在环境下几乎就是文件拷贝速度(16M/S)!
不知道各位有没有什么好的方法!



------解决方案--------------------
能否把程序发布在服务器上,然后在存储过程中使用文件操作来解决?
又或者,你的程序放在哪里都可以,但是可以启用imp/exp来.导出的参数可以指定需要导出的数据.
例如 exp a/pwd@orcl file=c:\tt.dmp tables=(a.ta) query='WHERE ...' 

------解决方案--------------------
假如是10g的数据库的话,
可以使用data pump功能。它比原来的imp/exp的速度要快很多。大约2倍以上。导入的话,大约5-45倍。

PARALLEL参数可以用来设置线程数。

推荐用这个。
------解决方案--------------------
1、在公司端生成csv文件
2、ftp到服务器端
3、sqlldr