ORACLE数据库插入性能测试

测试环境基本信息:

OSWindows XP sp3

DBOracle 9.2.0.1 未启用归档

DB重做日志文件大小:100MB

硬盘型号:SAMSUNG HD161GJSATA-300,160G,7200rpm,8M cache

CPUIntel Core2 E84003.0G

内存:2G

 

通过HD Tune得到的硬盘基本测试信息,

IOPS66

读取:90MB/s

写入:82MB/s

 

测试表脚本:

 

create table T_EMPLOYEE

(

  ID            NUMBER(10not null,

  NAME          VARCHAR2(20not null,

  CREATE_DATE   DATE default sysdate not null,

  BIRTHDAY      DATE,

  ADDRESS       VARCHAR2(200),

  EMAIL         VARCHAR2(200),

  MOBILEPHONE   VARCHAR2(11),

  TELEPHONE     VARCHAR2(20),

  IDENTITY_CARD VARCHAR2(18),

  WEIGHT        NUMBER,

  HEIGHT        NUMBER

)

 

 

插入10万条记录,采用Java JDBC方式的测试结果如下(单位:秒):

 

执行方式

OCI
TCP/IP

OCI
IPC

thin
AutoCommit=true

thin
AutoCommit=false

Statement(test1)

69.84

67.03

66.96

42.81

PreparedStatement(test2)

40

37.18

39.21

12.66

PreparedStatement Batch(test3)

51.72

50.78

2.81

2.81

 

 

从测试结果可以看出,采用thin连接方式 batch插入的性能最好,而采用ocibatch插入性能未得到提高,也可能是bug

记得以前在ORACLE文档里说采用oci模式的性能最好,9i中经过测试完全不成立,我想可能是以前java本身性能的问题,现在java语言的性能已经非常好了,thin连接方式不管是从管理还性能方面来说都是首选了。

 

注:采用ocibatch插入性能未得到提高确实是BUG,后来把ORACLE客户端升级到9.2.0.8,花的时间只要6s,但还是比thin的方式差。

 

以下是测试程序源码:

import java.sql.*;

import java.util.Calendar;

 

public class inserttest {

      public static void test1(Connection iConn) throws SQLException{

            Statement statement = iConn.createStatement();

            String str_i;

            for (int i=1;i<10000;i++) {

                  str_i=new Integer(i).toString();

                  String vSQL = "insert into t_employee(id,name,birthday,address,email,mobilephone,telephone,identity_card,weight,height)/n"

                              + "values(seq_t_employee_id.nextval,'张三"+str_i+ "',sysdate - "+str_i+","

                              + "'上海市南京东路11203"+str_i+"',"

                              + "'abcd"+str_i+"@gmail.com',"

                              + "'138'|| trim(to_char("+str_i+", '00000000')),"

                              + "'021-'|| trim(to_char("+str_i+", '00000000')),"

                              + "'3504561980' || trim(to_char("+str_i+", '00000000')),"

                              + "64,1.72)";

                  //System.out.println(vSQL);

                  statement.executeUpdate(vSQL);

            }

      }

 

      public static void test2(Connection iConn) throws SQLException{

            String vSQL = "insert into t_employee(id,name,birthday,address,email,mobilephone,telephone,identity_card,weight,height)/n"

                  + "values(seq_t_employee_id.nextval,'张三'||?,sysdate - ?,"

                  + "'上海市南京东路11203'||?,"

                  + "'abcd'||?||'@gmail.com',"

                  + "'138'|| trim(to_char(?, '00000000')),"

                  + "'021-'|| trim(to_char(?, '00000000')),"

                  + "'3504561980' || trim(to_char(?, '00000000')),"

                  + "64,1.72)";    

            PreparedStatement ps = iConn.prepareStatement(vSQL); 

            String str_i;

            for (int i=1;i<10000;i++) {

                  str_i=new Integer(i).toString();

                  ps.setString(1, str_i);

                  ps.setString(2, str_i);

                  ps.setString(3, str_i);

                  ps.setString(4, str_i);

                  ps.setInt(5, i);

                  ps.setInt(6, i);

                  ps.setInt(7, i);

                  ps.executeUpdate();

            }

      }    

 

      public static void test3(Connection iConn) throws SQLException{

            String vSQL = "insert into t_employee(id,name,birthday,address,email,mobilephone,telephone,identity_card,weight,height)/n"

                  + "values(seq_t_employee_id.nextval,'张三'||?,sysdate - ?,"

                  + "'上海市南京东路11203'||?,"

                  + "'abcd'||?||'@gmail.com',"

                  + "'138'|| trim(to_char(?, '00000000')),"

                  + "'021-'|| trim(to_char(?, '00000000')),"

                  + "'3504561980' || trim(to_char(?, '00000000')),"

                  + "64,1.72)";    

            PreparedStatement ps = iConn.prepareStatement(vSQL); 

            String str_i;

            for (int i=1;i<10000;i++) {

                  str_i=new Integer(i).toString();

                  ps.setString(1, str_i);

                  ps.setString(2, str_i);

                  ps.setString(3, str_i);

                  ps.setString(4, str_i);

                  ps.setInt(5, i);

                  ps.setInt(6, i);

                  ps.setInt(7, i);

                  ps.addBatch();

                  //ps.executeUpdate();

            }

            ps.executeBatch();

      }    

           

      public static void main(String[] args) throws ClassNotFoundException,SQLException {

            Class.forName("oracle.jdbc.driver.OracleDriver");

            //Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:mydb", "yzs", "yzs");

            Connection conn = DriverManager.getConnection("jdbc:oracle:oci8:@mydb""yzs""yzs");

            java.util.Date d1=Calendar.getInstance().getTime();

            conn.setAutoCommit(false);

            test2(conn);

            java.util.Date d2= Calendar.getInstance().getTime();

            System.out.println("es:"+(d2.getTime()-d1.getTime())+"ms");

            conn.commit();

            conn.close();

      }

}

 

采用服务器PL/SQL 方式插入10万条记录的测试结果如下:

注:t_e1t_employee同样的表结构

 

执行方式

说明

运行时间

(单位:秒)

pl/sql insert(脚本1

普通insert

3.203

pl/sql forall insert(脚本2

从一个表BULK COLLECT INTO到目标表

0.578

insert into select *(脚本3

使用insert into select方式插入

0.156

insert /*+ append*/  into select *(脚本4

append hint的插入

0.234

 

从测试结果分析,采用insert into select 的方式最快,只要0.156s,根据数据量统计,平均每行大小为134字节,总共插入数据量为134*100000=12.78MB,可得每秒约插入81MB的数据,基本上达到了硬盘的上限。

而采用append hint插入反而更慢,从同事讨论结果得到,采用appendinsert会采用direct-path插入,因此数据会直接写入数据文件,所以消耗的时间更多。

 

--------------------------------------------脚本1--------------

declare

  i integer;

begin

  for i in 1 .. 100000 loop

    insert into t_employee

      (id,

       name,

       birthday,

       address,

       email,

       mobilephone,

       telephone,

       identity_card,

       weight,

       height)

    values

      (

      seq_t_employee_id.nextval,

       '张三' || i,

       sysdate - i,

       '上海市南京东路11203' || i,

       'abcd' || i || '@gmail.com',

       '138' || trim(to_char(i, '00000000')),

       '021-' || trim(to_char(i, '00000000')),

       '3504561980' || trim(to_char(i, '00000000')),

       64,

       1.72);

  end loop;

  commit;

end;

--------------------------------------------脚本1--------------

 

--------------------------------------------脚本2--------------

DECLARE

  TYPE table_t_employee IS TABLE OF t_employee%ROWTYPE;

  v_table table_t_employee;

BEGIN

  SELECT * BULK COLLECT INTO v_table FROM t_employee;

  FORALL idx IN 1 .. v_table.COUNT

    INSERT INTO t_e1 VALUES v_table (idx);

  COMMIT;

END;

--------------------------------------------脚本2--------------

 

 

--------------------------------------------脚本3--------------

insert into t_e1  select * from t_employee

--------------------------------------------脚本3--------------

 

 

--------------------------------------------脚本4--------------

insert /*+ append*/  into t_e1  select * from t_employee

--------------------------------------------脚本4-------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值