大数据量的两个表数据复制的一些经验总结

1.如果两个表的数据结构一样,可以考虑很多种方式:

(1)create table as select * from tbl_name;

(2) insert /*+ append*/ into tbl_name select * from  tbl_name,如果软件平台与硬件平台够好,可以考虑加入parallel的hits。

(3)引入脚本:      

DECLARE
maxnum number defult 5000;
CURSOR cur IS
SELECT FROM aa;--定义游标
TYPE rec IS TABLE OF aa%ROWTYPE;--定义类型
recs rec;
BEGIN
OPEN cur; --打开游标

LOOP --循环条件

EXIT WHEN cur%NOTFOUND;--游标结束条件
FETCH cur BULK COLLECT --取游标里的值
   INTO recs LIMIT maxnum; --提交条件,每5000条提交
FORALL i IN 1 .. recs.COUNT --这个是个计数器,用来确保提交的条数,也是循环
   INSERT INTO bb VALUES recs (i);--插入目标表
COMMIT--提交
END LOOP; --停止循环
CLOSE cur;--关闭游标1,

END;

这种方式适用于要两个表结构一样的情况。


2.两个表结构不一样,方法也是类似的:

(1)insert /*+ append*/ into tbl_name(col1,col2,....) select col1,col2,... from  tbl_name,如果软件平台与硬件平台够好,同样可以考虑加入parallel的hits。如果对select语句进行列值处理,比如函数,性能影响很大。


3.复制千万级数据表时用的存储过程

CREATE OR REPLACE PROCEDURE "LARGEDATA_INSERT" (ip_table_name   in varchar2, --目标表
                                          ip_table_column in varchar2, --目标字段
                                          ip_table_select in varchar2, --SELECT 查询语句
                                          return_result   out number --返回的结果1,表示成功,0表示失败
                                          ) as
--适合大数据量的插入模板  create Templates by chenzhoumin 20110614
  runTime number;--运行总次数
  i       number;--当前行数
  amount  number;--总行数
  s_sql   varchar2(10000);--SQL语句
  e_sql   varchar2(10000);--执行SQL语句
  countNumber number;--一次插入的数据量
begin
  --set serveroutput on size 20000000000000
  countNumber := 10000;
  return_result := 0; --开始初始化为0
  --核必逻辑内容,可根据具体的业务逻辑来定义,统计数据总行数
  s_sql := 'select count(1) from (' || ip_table_select || ')';
  execute immediate s_sql
    into amount;
  --每100万提交一次
  runTime := amount mod countNumber;
  if (runTime > 0) then
    runTime := 1 + trunc(amount / countNumber);
  end if;
  if (runTime = 0) then
    runTime := 0 + trunc(amount / countNumber);
  end if;
  FOR i IN 1 .. runTime LOOP
    e_sql := 'insert into '||ip_table_name ||'
    ('||ip_table_column ||')
     select '|| ip_table_column ||'
     from
     (select selectSec.*, rownum rownumType
          from ('|| ip_table_select ||') selectSec
         WHERE ROWNUM <= '|| i * countNumber ||')
    WHERE rownumType > '||(i - 1) * countNumber;
    dbms_output.enable(99999999999999);
    dbms_output.put_line(e_sql);
    execute immediate e_sql;
    --提交
    commit;
  END LOOP;
  return_result := 1;
  return;
exception
  when others then
    return_result := 0;
    raise;
    dbms_output.enable(99999999999999);
    dbms_output.put_line('结束');
    return;
end;
其实这个存储过程当查询到数据千万以后也是挺慢的。


你可能感兴趣的:(数据库)