您的位置:首页 > 数据库 > Oracle

java 操作Oracle 批量入库的问题

2014-03-19 11:58 393 查看
java 操作Oracle 批量入库的问题

先说下我运行的环境:

Windows7 64位操作系统

(四核)Intel i5-2300 CPU @2.80GHz

内存4G

硬盘1T

Jdk1.6+MyEclipse8.6 for Spring+ojdbc14.jar

Oracle10.2.0+PLSQL7.1.4.1390

情况是这样的,今天一个朋友说用了我说的Oracle的Table类型批量入库过后,感觉慢了点。为此我在不考虑多线程的情况下,分别用“Oracle的 自定义类型定义表类型”、“Oracle的基本类型定义表类型”、“JDBCBATCH”一次性向Oracle插入10000条数据的用时进行了测试。结 果让我很费解。在这里列出来,希望知道的能解答一下,万分感谢。

数据表:

数据表:
-- Create table
create table DATE_JH_INC_UDR_01
(
SERIAL_NUMBER    VARCHAR2(16) not null,
OPR_TYPE         VARCHAR2(10) not null,
SERV_CODE        VARCHAR2(10) not null,
SP_CODE          VARCHAR2(10) not null,
OPER_CODE        VARCHAR2(20) not null,
INPUT_START_DATE DATE,
INPUT_END_DATE   DATE,
OPR_TIME         DATE,
EFF_TIME         DATE not null,
OPR_SOURCE       VARCHAR2(10),
THIRD_DN         VARCHAR2(30),
CHRG_TYPE        VARCHAR2(10)
);
-- Create/Recreate primary, unique and foreign key constraints
alter table DATE_JH_INC_UDR_01
add constraint PK_DATE_JH_INC_UDR_01 primary key (SERIAL_NUMBER, OPR_TYPE, SERV_CODE, SP_CODE, OPER_CODE, EFF_TIME);
-- Create/Recreate indexes
create index IDX_DATE_JH_INC_UDR_011 on DATE_JH_INC_UDR_01 (SP_CODE, OPER_CODE);


一、采用Oracle“基本类型”定义表类型入库。

  数据库准备:

  数据库准备:
CREATE OR REPLACE TYPE D_SERIAL_NUMBER IS TABLE OF NVARCHAR2(16);
CREATE OR REPLACE TYPE D_OPR_TYPE IS TABLE OF NVARCHAR2(2);
CREATE OR REPLACE TYPE D_SERV_CODE IS TABLE OF NUMBER(10);
CREATE OR REPLACE TYPE D_SP_CODE IS TABLE OF NVARCHAR2(10);
CREATE OR REPLACE TYPE D_OPER_CODE IS TABLE OF NVARCHAR2(20);
CREATE OR REPLACE TYPE D_INPUT_START_DATE IS TABLE OF NVARCHAR2(25);
CREATE OR REPLACE TYPE D_INPUT_END_DATE IS TABLE OF NVARCHAR2(25);
CREATE OR REPLACE TYPE D_OPR_TIME IS TABLE OF NVARCHAR2(25);
CREATE OR REPLACE TYPE D_EFF_TIME IS TABLE OF NVARCHAR2(25);
CREATE OR REPLACE TYPE D_OPR_SOURCE IS TABLE OF NVARCHAR2(2);
CREATE OR REPLACE TYPE D_THIRD_DN IS TABLE OF NVARCHAR2(30);
CREATE OR REPLACE TYPE D_CHRG_TYPE IS TABLE OF NVARCHAR2(2);

CREATE OR REPLACE PROCEDURE ARRAY_TO_IBOSS_UDR2(V_1 D_SERIAL_NUMBER,V_2 D_OPR_TYPE,V_3 D_SERV_CODE,V_4 D_SP_CODE,V_5 D_OPER_CODE,V_6 D_INPUT_START_DATE,V_7 D_INPUT_END_DATE,V_8 D_OPR_TIME,V_9 D_EFF_TIME,V_10 D_OPR_SOURCE,V_11 D_THIRD_DN,V_12 D_CHRG_TYPE,O_ERR OUT VARCHAR2,SUCC_COUNT OUT NUMBER,FAIL_COUNT OUT NUMBER)
AS
I INTEGER;
BEGIN
I:=0;
SUCC_COUNT:=0;
FAIL_COUNT:=0;
WHILE I<V_1.COUNT LOOP
BEGIN
I:=I+1;
INSERT INTO DATE_JH_INC_UDR_01 VALUES(V_1(I),V_2(I),V_3(I),V_4(I),V_5(I),TO_DATE(V_6(I),'YYYY-MM-DD HH24:MI:SS'),TO_DATE(V_7(I),'YYYY-MM-DD HH24:MI:SS'),TO_DATE(V_8(I),'YYYY-MM-DD HH24:MI:SS'),TO_DATE(V_9(I),'YYYY-MM-DD HH24:MI:SS'),V_10(I),V_11(I),V_12(I));
SUCC_COUNT:=SUCC_COUNT+1;
EXCEPTION
WHEN OTHERS THEN
FAIL_COUNT:=FAIL_COUNT+1;
O_ERR := I||':'||SQLERRM;
END;
END LOOP;
END;


Java代码:

import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.sql.Date;
import java.util.List;

import oracle.jdbc.OracleConnection;

public class Jdbc {

/**
* @param args
* @throws ClassNotFoundException
* @throws SQLException
* @throws ParseException
*/
public static void main(String[] args) throws ClassNotFoundException, SQLException, ParseException {
System.out.println("----------这是使用JDBC入库--------");
long datebegin = System.currentTimeMillis();
List<Object[]> s = new ArrayList<Object[]>();
for (int i = 0; i < 10000; i++) {
Object[] o1 = new Object[12];
o1[0] = "0"+i;
o1[1] = "0";
o1[2] = "0";
o1[3] = "0";
o1[4] = "0";
o1[5] = "20131226";
o1[6] = "20131226";
o1[7] = "20131226";
o1[8] = "20131226";
o1[9] = "0"+i;
o1[10] = "0";
o1[11] = "0";
s.add(o1);
}
long end1 = System.currentTimeMillis();
System.out.println("组装list用时:"+(end1-datebegin)+"毫秒");

long date1 = System.currentTimeMillis();
Class.forName("oracle.jdbc.driver.OracleDriver");
OracleConnection conn = null;
conn = (OracleConnection)DriverManager.getConnection("jdbc:oracle:thin:@"+"127.0.0.1"+":1521:"+"orcl", "test", "root");
String sql = "INSERT INTO DATE_JH_INC_UDR_01 VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
long date2 = System.currentTimeMillis();
System.out.println("数据库连接准备用时:"+(date2-date1)+"毫秒");

long array1 = System.currentTimeMillis();
//设置1w条提交一次
/*final int batchSize = 10000;
int count = 0;*/
for (Object[] obj: s) {
ps.setString(1, obj[0].toString());
ps.setString(2, obj[1].toString());
ps.setString(3, obj[2].toString());
ps.setString(4, obj[3].toString());
ps.setString(5, obj[4].toString());
ps.setDate(6, getDate(obj[5].toString()));
ps.setDate(7, getDate(obj[6].toString()));
ps.setDate(8, getDate(obj[7].toString()));
ps.setDate(9, getDate(obj[8].toString()));
ps.setString(10, obj[9].toString());
ps.setString(11, obj[10].toString());
ps.setString(12, obj[11].toString());
ps.addBatch();
/*if(++count % batchSize == 0) {
ps.executeBatch();
}*/
}
long array2 = System.currentTimeMillis();
System.err.println("组装SQL用时:"+(array2-array1)+"毫秒");

long params1 = System.currentTimeMillis();
ps.executeBatch();
long params2 = System.currentTimeMillis();
System.out.println("执行用时:"+(params2-params1)+"毫秒");

long cl1 = System.currentTimeMillis();
ps.close();
conn.close();
long cl2 = System.currentTimeMillis();
System.out.println("关闭用时:"+(cl2-cl1)+"毫秒");

long end = System.currentTimeMillis();
System.out.println("入库总用时:"+(end-datebegin)+"毫秒"+"  秒数为:"+((end-datebegin)/1000.0));
}

public static Date getDate(String str) throws ParseException{
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
return new Date(df.parse(str).getTime());
}

  }


View Code
执行之前清除数据:TRUNCATE TABLE DATE_JH_INC_UDR_01;

测试结果:



这让我灰常怀疑Oracle做这个数据接口出来干什么?

  几个问题,想问问大家。

  第一,对这种大批量的数据入库,各位采用的都是用什么方式+多线程?

  第二,Oracle提供ARRAY跟TABLE跟OBJECT类型拿来入库的话,是不是性能真的像我测试这样?

  第三,如果你们用的不是JDBC的Batch方法,并且比它更快的,贴出来让我学习学习吧!

  第四,这里不考虑多线程问题,当然实际应用中多线程肯定要加上去的。

  第五,向看过我Oracle的ARRAY,TABLE类型批量入库的并且还拿到生产环境上去使用的同学致以歉意,是我坑了你们......

转载地址:http://bbs.csdn.net/topics/390733080
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: