问题:
   如何在单个事务操作中高效地将大批量数据插入某个表?
假定要在一次事务中生成10万条数据。要点:
    1) 可通过随机数来生成需要的数据;
    2)可以使用任何方法:
       PL/SQL, OCI External Procedures, Java stored procedure.要求最好能提供源代码。提供源代码并能有效工作者给高分。附:测试表
create table test1(
    data_id varchar2(12),
    primary key(data_id)
);

解决方案 »

  1.   

    1、使用COPY FROM ,,, TO ...
    2、表不建立索引。
      

  2.   

    一次插入999999条记录:insert into test1 select substr(sys_guid(),1,12) from all_objects a,allobjects b where rownum<1000000;
      

  3.   

    存储过程的话: PL/SQL
    外部程序使用: OCI
      

  4.   


     1. 使用DirectPath
        Insert /*+ append */  into ...
     2. 使用前可以先禁用索引,因为对索引的维护将产生大量重做日志文件 3. 使用FORALL关键字,例如(来自ASKTOM.ORACLE.COM):
         
       declare
         type numTab is table of number(4) index by binary_integer;
         data numTab;
         empty numTab;
      
       begin
           for j in 1 .. 5000 loop
               data(data.count+1) := j;
      
               if ( mod(data.count,1000) = 0 )
               then
                  forall i in 1 .. data.count
                     insert into test_for_ins values (data(i));
                   data := empty;
               end if;
     
    end loop;
     
             if ( data.count is not null )
      then
          forall i in 1 .. data.count
              insert into test_for_ins values (data(i));
             end if;
     
            commit;
        end;  4. 使用OCI,Pro*C可能会得到更快的效果.
      

  5.   

    使用DirectPath
        Insert /*+ append */  into ...
      

  6.   

    to leecooper0918:
    希望数据不是按顺序生成的。要求数据必须是随机生成的,在大批量的数据中每次检索是否有重复的数据也是十分耗时的。不用考虑多次插入数据的情况,只需生成一次。
      

  7.   

    前面不是说了啊,用DirectPath方式导入,导完后做一次热备份.
      

  8.   

    方法一:批量插入        
            insert /*+append */ into select (You need columns) from tablename;
    方法二:用户间复制数据
            copy from user/pw@sid to user create table2 using select * from table1;
    方法三:sqlldr最快
    我在如下环境测试ok
    环境说明:
    数据库:Oracle8.1.6OEM;
    系  统:Windows2000 Server.
    *******************************************************************************************
    用记事本创建控制文件input.ctl,内容如下:load data
    infile 'test.txt' --数据文件
    append into table Test
    fields terminated by '|' --或者是x'09'来标识,也即字段终止与制表符TAB
    ( --字段名称
    cp_bh char(30),
    mc char(50),
    cp_ljmc char(100),
    zyh char(20),
    dj
    )*******************************************************************************************文本文件test.txt中的内容格式,例如下面10300108200|XPB65-113S|后盖  PP  0.34kg|0030200525      |3.42000008
    10300108200|XPB65-113S|洗涤桶盖  浅兰透明ABS|0030200877      |15.52000046一般情况都是相互之间导出导入数据,比方说从excel导出的数据你可以将其保存为:制表符分隔,起名为test,……,等等。
    *******************************************************************************************
    使用sql*loader进行数据导入(sqlldr -? 查看帮助)在“运行”里执行,命令如下: sqlldr username/pw control=路径\input.ctl data=路径\test.txt log=路径 bad=路径
      

  9.   

    谢谢各位,
    以上方法本人都明白,可能是因为我说的范围太宽了。现在再限定一下:必须使用 OCI External Procedures 或 Pro*C外部过程,是放在服务端的;
    或者使用Pro*C编译的Exe客户端也可以,稍作转换即可成为外部过程。我正在 使用Pro*C 实现数据库的Bulk insert 操作,但结果不太理想。
    有愿意帮忙的吗?这里先谢谢了。
      

  10.   


     既然程序放在服务端,也可以考虑做成存储过程啊.我上面都说了拿
     forall实现,速度很快DI
      

  11.   

    感觉oracle的sql load 应该可以的 速度也不错 可以试验一下 我们这里的数据都是使用这个方法
      

  12.   

    to leecooper0918(PajeroFans):
    你说的没错,可以写成存储过程,但是在存储过程中大批量的不重复的随机数据的如何生成呢?
      

  13.   

    用proc实现bulk insert的操作的方法也是可取的,可能是你程序上还有些问题。
      

  14.   

    什么算高效? 目前,我们这边也有每天100多万的数据倒入另外一个表.我们的策略就是:
    对表进行分区,索引也分区,
    insert之前,将该分区的分区置为无效.
    insert /*append*/.....
    insert之后,重新建立索引至少目前,对于100多万的数据,我们觉得还可以忍受.
      

  15.   

    如果是做插入操作,大家知道,I/O次数越多,效率越低,因此要尽量避免
    要提高效率,最好是将所有的记录select出来,然后一次插入,也就是说做一次insert。
    举例实现方法:找一个大数据量表tbl_big,记录数100万
    insert into test(a) select seq_a.nextval from tbl_big where rownum <= 500000;
    commit;
    其中select语句在内存中执行,非常快;insert语句一次插入,也非常快!几秒钟搞定!
      

  16.   

    不 Agree 楼上的:
      要提高效率,最好是将所有的记录select出来,然后一次插入,
      也就是说做一次insert
       --------------------?  理论上是这样,select 操作完全在内存中进行是最好,但是会占用
      大量内存,同时对回滚段的要求也很大,弄不好就会出现" snapshot
      too old的错误"  我还是比较赞同  insert /*+ append */ 的方式.
      

  17.   

    一次插入999999条记录:insert into test1 select substr(sys_guid(),1,12) from all_objects a,allobjects b where rownum<1000000;构造笛卡尔积最快啊,呵呵