问题:
如何在单个事务操作中高效地将大批量数据插入某个表?
假定要在一次事务中生成10万条数据。要点:
1) 可通过随机数来生成需要的数据;
2)可以使用任何方法:
PL/SQL, OCI External Procedures, Java stored procedure.要求最好能提供源代码。提供源代码并能有效工作者给高分。附:测试表
create table test1(
data_id varchar2(12),
primary key(data_id)
);
如何在单个事务操作中高效地将大批量数据插入某个表?
假定要在一次事务中生成10万条数据。要点:
1) 可通过随机数来生成需要的数据;
2)可以使用任何方法:
PL/SQL, OCI External Procedures, Java stored procedure.要求最好能提供源代码。提供源代码并能有效工作者给高分。附:测试表
create table test1(
data_id varchar2(12),
primary key(data_id)
);
2、表不建立索引。
外部程序使用: OCI
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可能会得到更快的效果.
Insert /*+ append */ into ...
希望数据不是按顺序生成的。要求数据必须是随机生成的,在大批量的数据中每次检索是否有重复的数据也是十分耗时的。不用考虑多次插入数据的情况,只需生成一次。
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=路径
以上方法本人都明白,可能是因为我说的范围太宽了。现在再限定一下:必须使用 OCI External Procedures 或 Pro*C外部过程,是放在服务端的;
或者使用Pro*C编译的Exe客户端也可以,稍作转换即可成为外部过程。我正在 使用Pro*C 实现数据库的Bulk insert 操作,但结果不太理想。
有愿意帮忙的吗?这里先谢谢了。
既然程序放在服务端,也可以考虑做成存储过程啊.我上面都说了拿
forall实现,速度很快DI
你说的没错,可以写成存储过程,但是在存储过程中大批量的不重复的随机数据的如何生成呢?
对表进行分区,索引也分区,
insert之前,将该分区的分区置为无效.
insert /*append*/.....
insert之后,重新建立索引至少目前,对于100多万的数据,我们觉得还可以忍受.
要提高效率,最好是将所有的记录select出来,然后一次插入,也就是说做一次insert。
举例实现方法:找一个大数据量表tbl_big,记录数100万
insert into test(a) select seq_a.nextval from tbl_big where rownum <= 500000;
commit;
其中select语句在内存中执行,非常快;insert语句一次插入,也非常快!几秒钟搞定!
要提高效率,最好是将所有的记录select出来,然后一次插入,
也就是说做一次insert
--------------------? 理论上是这样,select 操作完全在内存中进行是最好,但是会占用
大量内存,同时对回滚段的要求也很大,弄不好就会出现" snapshot
too old的错误" 我还是比较赞同 insert /*+ append */ 的方式.