May 2012
M T W T F S S
« Apr    
 123456
78910111213
14151617181920
21222324252627
28293031  

史上最快,最具可扩展性的文本导出方法

Kaya 发表于 os2ora.com

这个题目有点吓人,不过既然这么说,当然有其强有力的后台做支撑。如果说一句谎言必须用更多的谎言来圆的话,一句真话恐怕也要用更多的真话来阐述,呵呵,且让我慢慢道来。

Oracle上的技术,其实是相当开放的,这里提到的这种文本导出方法,其实在网上已经有人做了很好的论述和实现。只不过本着独乐乐不如众乐乐的想法,在这里再推广一把罢了。

首先明确一点,文本导入到数据库中,或者把数据从数据库中导出为文本格式,这都是极其消耗CPU的操作。所以,导出速度首先取决于系统CPU的运算能力。基于大数据量处理的系统一般都是多节点的RAC系统,于是,文本导出的一个主要议题就是:如何利用起所有RAC节点的所有CPU的运算能力。

Oracle的Data Pump其实就达到了这个目标,在RAC系统中运行Data Pump,通过设置parallel参数,导出作业会在所有RAC节点运行,从而利用起系统可能存在的空闲的CPU资源。不过,Data Pump没有提供导出为文本格式的方法。

如果自己实现这种并行机制呢?那也未尝不可,目前anysql.net上有个类似的工具,叫做sqluldr2,应该就是朝着这个方向在发展。目前作者实现了对海量大表进行自动切片的算法,我想可能下一步的动作应该是在所有的RAC节点上启动多个sqluldr2实例进行导出,衷心希望这个工具能达到更好的性能。

如果能利用起Oracle本身的并行机制,那应该是一件高效并且简单的实现。只要想想Oracle投入了多少人力开发设计并行这个技术,想想并行技术在Oracle版本中的悠久历史,我们会毫不怀疑地相信并行技术的高效性,可扩展性与稳定性。

并行技术的首要设计目标就是把所有可能空闲的系统资源利用起来。例如对于下面一个简单的查询

SELECT *FROM big_table

如果现在的系统有8个节点,每个节点有8个CPU,那么这时Oracle会启动8*8*parallel_threads_per_cpu =128个并行进程。每个进程负责扫描表big_table的1/128了。与串行执行相比,扫描时间理论上会缩小为1/128,“理论上”背后主要的潜台词就是系统没有IO瓶颈了。

设想一下,如果这128个进程在扫描表的同时,把这些数据同时写到文本文件中,这不就是我们所想要的并行文本导出功能吗?关键是找到一个途径,告诉这些并行进程在扫描的同时执行写出数据到文本中这个操作。

这个途径,Oracle中以pipelined table function的形式提供。这是一个PL/SQL函数,我们只要在这个函数里面把每个并行进程接收到的数据通过UTL_FILE.PUT函数写到文本中就达到了我们的目标了。

上面提到的是利用Oracle本身的并行机制实现并行多节点导出数据的主要思路。至于具体的实现,可以直接参考www.oracle-developer.net上的文章:improving performance with pipelined table functions,这篇文章详细解释了pipelined table functions在数据导入和转换(ETL),数据导出方面的杰出贡献,具体地说,数据导出部分的子标题是asynchronous data unloading with parallel pipelined functions。同时,文章提到的脚本应该是能直接下载和运行的。

我们再深入一步,到目前为止,我们应该能够穷尽整个RAC系统所有节点的CPU处理能力,仅仅是“应该”而已。想像一种情况,如果导出文件系统的IO性能很差,不能足够快地消化上面提到的128个并行进程的写入操作,那么瓶颈就会出现在磁盘IO上了。按照我们的经验,128个进程提供接近1GB每秒的写出量还是有可能了。要找到一个文件服务器提供这么高的带宽对于很多数据中心而言还是不现实的。

解决方法在于减少对磁盘的IO量,一个马上想到的方法就是对并行进程写出的数据进行压缩。然后再把压缩后的数据写往磁盘。在Unix系统中,这可能通过文件管道的形式实现:并行进程把数据写入管道文件中,gzip进程通过读取管道文件,对数据进行压缩,然后再把它写入到目标磁盘中。

假设gzip的压缩率为1:10,于是我们实现了把1GB/s的写入下降到100MB/s,这是一个大部分文件服务器能达到的指标了。同时,我们在导出的同时做了后面我们很可能做的事情,压缩数据以便于减少数据空间或者以利于网络传输。

不知道上面的论述能否对得起这篇文章的标题 :)

1 comment to 史上最快,最具可扩展性的文本导出方法

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">