Java Oracle 插入100万条记录

时间:2022-05-19 23:19:11
如何能够缩短时间?
[img=http://qun.qq.com/air/#3757691/impress/show/alid/1f1f1f1f-1111-1111-1111-1f1f1f1f/pd/fa56a334-d567-4523-6594-57a41c9e2650#3757691/impress/show/alid/1f1f1f1f-1111-1111-1111-1f1f1f1f/pd/fa56a334-d567-4523-6594-57a41c9e2650][/img]

public static void main(String[] args) throws ClassNotFoundException, SQLException
{
Connection con = DBUtil.getConnection();
con.setAutoCommit(false);
PreparedStatement ps =con.prepareStatement("insert into BigInsert nologging values (?)");
long start = System.currentTimeMillis();
for(int i=1;i<1000001;i++)
{
ps.setInt(1, i);
//ps.executeUpdate();
ps.addBatch();
if(i%10000==0)
{
ps.executeBatch();
ps.clearBatch();
}
}
con.commit();
long end = System.currentTimeMillis();
System.out.println(end-start);
ps.close();
con.close();

}


能不能在2~5S内完成?

40 个解决方案

#1


那你测试测试吧。。不就知道了么、?

#2


测试了,要5~10S。。。
可以提供更快的办法么?

#3


加大你 电脑的内存 或者有其他的办法,,,我就不知道了。

#4


dbms那边没话说
就在于自己写的程序
和硬件了

#5


使用存储过程,因为你的insert的值是一定的。

#6


存储过程一样,普通机器直接使用oracle的存储过程也需要一定的时间。
提高性能需要硬件设备的支持,楼主的代码已经够完美的了,无可挑剔。但是有一个问题是
循环外面也需要加


ps.executeBatch();
ps.clearBatch();
//避免不是整数倍时,这部分的sql不执行

#7


使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。

#8


5s内完成我感觉是不可能的。

应该是分钟级的,不应该是秒级别的。

#9


这程序很完美了,不好提高了吧

#10


引用 8 楼 rumlee 的回复:
5s内完成我感觉是不可能的。

 应该是分钟级的,不应该是秒级别的。

我感觉也是,应该没有那么快

#11


。。。用sql语句应该就是效率最高了的

#12


程序性能方面:
1。提高插入速度,必须用多线程,对数据分批处理。

数据库承载方面:
2。利用数据库的分布特性,分布到几台数据服务器上,进行数据分流,应该可以提高插入效率和避免影响查询性能。最佳的情况是,假设有十台服务器,则数据插入时可以以轮插方式分插进去。

2。利用数据库的发布特性,可以分成专门插入的数据库和专门查询的数据库。专门插入的数据库在一批数据插入之后,利用一个访问数量较少的时间向专门查询的数据库作发布。

#13


引用 12 楼 zl3450341 的回复:
Java code程序性能方面:1。提高插入速度,必须用多线程,对数据分批处理。

数据库承载方面:2。利用数据库的分布特性,分布到几台数据服务器上,进行数据分流,应该可以提高插入效率和避免影响查询性能。最佳的情况是,假设有十台服务器,则数据插入时可以以轮插方式分插进去。2。利用数据库的发布特性,可以分成专门插入的数据库和专门查询的数据库。专门插入的数据库在一批数据插入之后,利用一个访问数量较少的时间向专门查询的数据库作发布。


楼上高见,支持!

#14


引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。

可以试试

#15


最近我也在研究jdbc。我想问下,你执行完了代码后事在你的dbms中自动就创建了个数据项吗?如果是怎么查看创建的数据项

#16


直接insert into tablename values select * from tablenameA having column 《= 100W

#17


table 中不要有索引

#18


你这100万都是一个数啊,也不是一个信息数组啊

#19


写个存储过程,然后调用

#20


恩,可以试试多线程

#21


说话不腰疼啊,用上面的程序5秒能插入100万?

#22


建议100 条记录,提交一次事务!

#23


使用多线程,100w数据开10个线程,10w一插,试下,公司做过多线程查询,效果不错,但是倒没多线程的插入,把结果发来看看。

#24


用多线程,用内存数据库,比较快。

#25


引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
 比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。


在单cpu的情况下,多线程并不会解决任何速度上的问题。因为在cpu时间片段上,仍旧是单线程的。

#26


把commit语句移到这个if块里面,事务不要太大

if(i%10000==0)
            {
                ps.executeBatch();
                ps.clearBatch();
            }

#27


呵呵。。。应该可以控制在2-5s的吧。

#28


insert /*+append*/ into t select * from dba_objects nologging;

SQL语句中的优化提示
APPEND : Only valid for INSERT .. SELECT. Allows INSERT to work like direct load ,把数据放到hwm后面的数据块中

再加上nologging 会更快。

可以试试

#29


我觉得多线程的效果也差不多, 楼主可以方式把batch的大小缩小到1000看看

#30


可以像 28 楼所说的,添加优化器,避免 Oracle 记录重做日志,这样也会减少一些 IO 操作。

PS:性能瓶颈在 IO 上,如果是 IO 瓶颈的话,那采用多个线程的话或许还不如一个线程来得快,毕竟磁盘的磁头只有一个。

#31


IO 操作的并发率为 0,也就是说不支持并发。

#32


如果是oralce 的话,用oraclePreparedStatemente, 或 直接写一个过程,直接调用过程  
还有,你先把数据库  表 设置为nologging,再使索引失索!你可以批处理的量调大点 

#33


多线程只有在多个[核心的]CPU上有用, 如果有N个CPU[核], 则线程数量为N或者N+1时效率最高.
多线程很多时候主要是为了阻止IO阻塞, 提高用户体验, 多任务同时进行, 而效率并不一定会提高, 甚至会降低效率.

#34


oracle 的 bulk insert

#35


存储过程应该好一点。

#36


该回复于2011-10-08 15:22:39被版主删除

#37


引用 25 楼 spiniper 的回复:
引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。



在单cpu的情况下,多线程并不会解决任何速度上的问题。因为在cpu时间片段上,仍旧是单线程的。

多线程是有效的,因为SQL操作的时间主要花在了和DB打交道的时间上了,如果使用多线程,会利用其这些时间片。即使是单核CPU

#38


LZ的速度,我觉得基本正常,毕竟有这么多的数据。如果再快一些的话,就要考虑使用命令行工具sqlldr了。当使用direct=true模式是会非常的快。但是会有副作用。比如会忽略所有的触发器以及检查,会索引会失效,然后在导入数据结束的时候会重建索引。如果是唯一索引,可能会重建失败而失效。如果真到这个速度不可接受的话。那么可以先将数据写入文件。现在的IO效率是远远超过DB的,然后再用sqlldr工具导入。基本上这个速度上提高几十倍是没问题的。

#39


It looks great

#40


呵呵,学习一下。

#1


那你测试测试吧。。不就知道了么、?

#2


测试了,要5~10S。。。
可以提供更快的办法么?

#3


加大你 电脑的内存 或者有其他的办法,,,我就不知道了。

#4


dbms那边没话说
就在于自己写的程序
和硬件了

#5


使用存储过程,因为你的insert的值是一定的。

#6


存储过程一样,普通机器直接使用oracle的存储过程也需要一定的时间。
提高性能需要硬件设备的支持,楼主的代码已经够完美的了,无可挑剔。但是有一个问题是
循环外面也需要加


ps.executeBatch();
ps.clearBatch();
//避免不是整数倍时,这部分的sql不执行

#7


使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。

#8


5s内完成我感觉是不可能的。

应该是分钟级的,不应该是秒级别的。

#9


这程序很完美了,不好提高了吧

#10


引用 8 楼 rumlee 的回复:
5s内完成我感觉是不可能的。

 应该是分钟级的,不应该是秒级别的。

我感觉也是,应该没有那么快

#11


。。。用sql语句应该就是效率最高了的

#12


程序性能方面:
1。提高插入速度,必须用多线程,对数据分批处理。

数据库承载方面:
2。利用数据库的分布特性,分布到几台数据服务器上,进行数据分流,应该可以提高插入效率和避免影响查询性能。最佳的情况是,假设有十台服务器,则数据插入时可以以轮插方式分插进去。

2。利用数据库的发布特性,可以分成专门插入的数据库和专门查询的数据库。专门插入的数据库在一批数据插入之后,利用一个访问数量较少的时间向专门查询的数据库作发布。

#13


引用 12 楼 zl3450341 的回复:
Java code程序性能方面:1。提高插入速度,必须用多线程,对数据分批处理。

数据库承载方面:2。利用数据库的分布特性,分布到几台数据服务器上,进行数据分流,应该可以提高插入效率和避免影响查询性能。最佳的情况是,假设有十台服务器,则数据插入时可以以轮插方式分插进去。2。利用数据库的发布特性,可以分成专门插入的数据库和专门查询的数据库。专门插入的数据库在一批数据插入之后,利用一个访问数量较少的时间向专门查询的数据库作发布。


楼上高见,支持!

#14


引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。

可以试试

#15


最近我也在研究jdbc。我想问下,你执行完了代码后事在你的dbms中自动就创建了个数据项吗?如果是怎么查看创建的数据项

#16


直接insert into tablename values select * from tablenameA having column 《= 100W

#17


table 中不要有索引

#18


你这100万都是一个数啊,也不是一个信息数组啊

#19


写个存储过程,然后调用

#20


恩,可以试试多线程

#21


说话不腰疼啊,用上面的程序5秒能插入100万?

#22


建议100 条记录,提交一次事务!

#23


使用多线程,100w数据开10个线程,10w一插,试下,公司做过多线程查询,效果不错,但是倒没多线程的插入,把结果发来看看。

#24


用多线程,用内存数据库,比较快。

#25


引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
 比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。


在单cpu的情况下,多线程并不会解决任何速度上的问题。因为在cpu时间片段上,仍旧是单线程的。

#26


把commit语句移到这个if块里面,事务不要太大

if(i%10000==0)
            {
                ps.executeBatch();
                ps.clearBatch();
            }

#27


呵呵。。。应该可以控制在2-5s的吧。

#28


insert /*+append*/ into t select * from dba_objects nologging;

SQL语句中的优化提示
APPEND : Only valid for INSERT .. SELECT. Allows INSERT to work like direct load ,把数据放到hwm后面的数据块中

再加上nologging 会更快。

可以试试

#29


我觉得多线程的效果也差不多, 楼主可以方式把batch的大小缩小到1000看看

#30


可以像 28 楼所说的,添加优化器,避免 Oracle 记录重做日志,这样也会减少一些 IO 操作。

PS:性能瓶颈在 IO 上,如果是 IO 瓶颈的话,那采用多个线程的话或许还不如一个线程来得快,毕竟磁盘的磁头只有一个。

#31


IO 操作的并发率为 0,也就是说不支持并发。

#32


如果是oralce 的话,用oraclePreparedStatemente, 或 直接写一个过程,直接调用过程  
还有,你先把数据库  表 设置为nologging,再使索引失索!你可以批处理的量调大点 

#33


多线程只有在多个[核心的]CPU上有用, 如果有N个CPU[核], 则线程数量为N或者N+1时效率最高.
多线程很多时候主要是为了阻止IO阻塞, 提高用户体验, 多任务同时进行, 而效率并不一定会提高, 甚至会降低效率.

#34


oracle 的 bulk insert

#35


存储过程应该好一点。

#36


该回复于2011-10-08 15:22:39被版主删除

#37


引用 25 楼 spiniper 的回复:
引用 7 楼 paullbm 的回复:
使用多线程方式进行插入。。
比如你可以使用5个线程,将100W进行分段,一个线程对应一个段。



在单cpu的情况下,多线程并不会解决任何速度上的问题。因为在cpu时间片段上,仍旧是单线程的。

多线程是有效的,因为SQL操作的时间主要花在了和DB打交道的时间上了,如果使用多线程,会利用其这些时间片。即使是单核CPU

#38


LZ的速度,我觉得基本正常,毕竟有这么多的数据。如果再快一些的话,就要考虑使用命令行工具sqlldr了。当使用direct=true模式是会非常的快。但是会有副作用。比如会忽略所有的触发器以及检查,会索引会失效,然后在导入数据结束的时候会重建索引。如果是唯一索引,可能会重建失败而失效。如果真到这个速度不可接受的话。那么可以先将数据写入文件。现在的IO效率是远远超过DB的,然后再用sqlldr工具导入。基本上这个速度上提高几十倍是没问题的。

#39


It looks great

#40


呵呵,学习一下。