问题现象

某客户环境,客户的业务使用jdbc驱动向其他操作系统上的yashandb插入90万条数据,耗时大约30分钟。

问题的风险及影响

影响客户的业务处理效率

问题影响的版本

所有的yashandb版本

问题发生原因

jdbc执行batch insert时,是有绑定变量的。在准备好了PreparedStatement以后,jdbc驱动要向yashandb server发送绑定变量的值。

由于网络带宽不足,这些绑定变量的值发送需要耗费一定时间,最终导致了插入数据效率降低。

解决方法及规避方式

提高jdbc所在操作系统与yashandb server所在操作系统网络之间的带宽

问题分析和处理过程

要插入数据表的ddl如下:

CREATE TABLE "LOCATION_INFO_INDEX000001"
(
"ID" VARCHAR(36) NOT NULL,
"VEHICLENO" VARCHAR(11) NOT NULL,
"VEHICLECOLOR" NUMBER(1,0) NOT NULL,
"MILEAGE" NUMBER(11,0) NOT NULL,
"LONGITUDE" NUMBER(16,6) NOT NULL,
"LATITUDE" NUMBER(16,6) NOT NULL,
"HEIGHT" NUMBER(11,0) NOT NULL,
"SPEED" NUMBER(11,0) NOT NULL,
"DIRECTION" NUMBER(11,0) NOT NULL,
"DATETIME" NUMBER(16,0) NOT NULL,
"DATE" VARCHAR(10) NOT NULL,
"ALARM" NUMBER(11,0) NOT NULL,
"STATE" NUMBER(11,0),
"MSGGNSSCENTERID" VARCHAR(255),
"MSGGNSSCENTERNAME" VARCHAR(255),
"INS" NUMBER,
"SEQ" NUMBER,
"UPDATESTATUS" NUMBER,
"UPDATETIME" VARCHAR2(50),
CONSTRAINT "LOCATION_INFO_INDEX000001_PKEY" PRIMARY KEY("ID")) ;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

使用如下的java代码作为jdbc客户端向yashandb server插入数据:

public void test_slow_table(Connection conn){
        try{
            //System.out.println(DBUtil.buildInsertMeta(conn, "SZSJYJTGK", "LOCATION_INFO_INDEX000001"));
            conn.setAutoCommit(false);
            PreparedStatement ps = conn.prepareStatement("insert into LOCATION_INFO_INDEX000001(ID ,VEHICLENO ,VEHICLECOLOR ,MILEAGE ," +
                    "LONGITUDE ,LATITUDE ,HEIGHT ,SPEED ,DIRECTION ,\"DATETIME\" ,\"DATE\" ,ALARM ,\"STATE\" ,MSGGNSSCENTERID ,MSGGNSSCENTERNAME ,INS ,SEQ ,UPDATESTATUS ," +
                    "add_time,UPDATETIME,by01,by02) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
 
            System.out.println("1: " + Instant.now());
            long start = System.currentTimeMillis();
            int base = 100900000;
            for(int i = base;i < base+100000; i++) {
                //ID                                                               NOT NULL  VARCHAR(144)
                //System.out.println("add id_" + i);
                ps.setString(1, "id_" + i);
                //VEHICLENO                                                        NOT NULL  VARCHAR(44)
                ps.setString(2, "abcd");
                //VEHICLECOLOR                                                     NOT NULL  NUMBER(1)
                ps.setInt(3,1);
                //MILEAGE                                                          NOT NULL  NUMBER(11)
                ps.setInt(4, i);
                //LONGITUDE                                                        NOT NULL  NUMBER(16,6)
                ps.setInt(5, i);
                //LATITUDE                                                         NOT NULL  NUMBER(16,6)
                ps.setInt(6,i);
                //HEIGHT                                                           NOT NULL  NUMBER(11)
                ps.setInt(7,i);
                //SPEED                                                            NOT NULL  NUMBER(11)
                ps.setInt(8,i);
                //DIRECTION                                                        NOT NULL  NUMBER(11)
                ps.setInt(9,i);
                //DATETIME                                                         NOT NULL  NUMBER(16)
                ps.setInt(10,i);
                //DATE                                                             NOT NULL  VARCHAR(40)
                ps.setString(11, "abcd");
                //ALARM                                                            NOT NULL  NUMBER(11)
                ps.setInt(12,i);
                //STATE                                                                      NUMBER(11)
                ps.setInt(13,i);
                //MSGGNSSCENTERID                                                            VARCHAR(1020)
                ps.setString(14,StringUtil.buildString(256));
                //MSGGNSSCENTERNAME                                                          VARCHAR(1020)
                ps.setString(15,StringUtil.buildString(256));
                //INS                                                                        NUMBER
                ps.setInt(16,i);
                //SEQ                                                                        NUMBER
                ps.setInt(17,i);
                //UPDATESTATUS                                                               NUMBER
                ps.setInt(18,i);
                //ADD_TIME                                                                   TIMESTAMP
                ps.setTimestamp(19,new Timestamp(System.currentTimeMillis()));
                //UPDATETIME                                                                 TIMESTAMP
                ps.setTimestamp(20,new Timestamp(System.currentTimeMillis()));
                ps.setString(21,StringUtil.buildString(256));
                ps.setString(22,StringUtil.buildString(256));
 
 
                ps.addBatch();
                if((i+1)%1000 == 0){
                    System.out.println("21:" + Instant.now());
                    ps.executeBatch();
                    conn.commit();
                }
            }
            System.out.println("2:" + Instant.now());
            ps.executeBatch();
            System.out.println("3:" + Instant.now());
            conn.commit();
            System.out.println("4:" + Instant.now());
            long end = System.currentTimeMillis();
            System.out.println("cost:" + (end-start) + " ms");
 
        }catch (Exception e){
            e.printStackTrace();
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.

jdbc客户端和yashandb server不在一个操作系统时,其网络带宽大概为800KB/s

【YashanDB数据库】由于网络带宽不足导致的jdbc向yashandb插入数据慢_System

插入10万条数据,大概耗时130s:

【YashanDB数据库】由于网络带宽不足导致的jdbc向yashandb插入数据慢_绑定变量_02

同样的jdbc代码在运行yashandb的操作系统上执行,耗时4s左右:

【YashanDB数据库】由于网络带宽不足导致的jdbc向yashandb插入数据慢_bc_03

可以得出结论,耗时基本都花在了网络传输上。

经验总结

客户端代码在yashandb运行的操作系统上执行,可以去除掉网络传输的影响,方便分析问题