对于有LONG类型的列,insert..select的方式显然是不行的,可以通过exp/imp的方式,但是这种方式速度非常慢,其原因在于imp时一行一行地插入表。有另外一种方式,即sqlplus的copy命令,下面是一个示例: view plaincopy to clipboardprint?
spool copy_long_table_1.log
conn / as sysdba
set copycommit=2000
set arraysize 30
set long 10485760
copy from system/xxxx@source_db append username.table_name using select * from username.table_name;
spool off
exit
spool copy_long_table_1.log
conn / as sysdba
set copycommit=2000
set arraysize 30
set long 10485760
copy from system/xxxx@source_db append username.table_name using select * from username.table_name;
spool off
exit
不过,sqlpus的copy命令不支持有timestamp和lob列类型的表。如果有timestamp类型的表,可以通过在exp时,加上rowid的条件,将一个表分成多个部分同时操作,对于有lob类型的表,也可以同样处理(因为insert …select方式下,有lob类型列时,也同样是一行一行地插入)。注意在这种方式下,就不能使用direct的方式exp/imp。下面是exp导出时parfile示例:
对于特别大的分区表,虽然使用并行可以提高速度,但是受限于单个进程(不能跨DB LINK进行并行事务,只能并行查询,也即insert..select只能是SELECT部分才能进行并行)的处理能力,这种方式下速度仍然有限。可以并行将数据插入多个中间表,然后通过exchange partition without validation 的方式,交换分区,这种方式将会大大提高了速度。
有朋友可能会问,为什么不并行直接插入分区表,当然如果是非direct path(append)方式,则是没问题的,但是这种方式插入的性能较低。而direct path的方式,会在表上持有mode=6(互斥)的TM锁,不能多个会话同时插入。(update: 在insert 时使用这样的语句:insert into tablename partition (partname) select * from tablename where ….,更简单更有效率。)