使用insert on duplicate key update 模式导入1万条数据,用了10分钟

【产品名称】oceanbase

【产品版本】3.1.1

【问题描述】java 使用insert on duplicate key update 模式导入1万条数据到一个9个普通字段的空表,用了10分钟,而直接insert 1万条数据,只需要1秒,请问是那里的问题呢? 感谢

相关配置以及关键代码

1、jdbc的url: jdbc:mysql://192.168.90.32:2883/test?useSSL=false;useUnicode=true;characterEncoding=UTF-8;rewriteBatchedStatements=true;allowMultiQueries=true;useLocalSessionState=true 2、租户资源: 内存 36G,cpu 2 3、mysql-connector-java版本: 5.1.47 4、关键代码 PreparedStatement pstmt = null; try { // tid是主键, data+code+type是唯一性约束 String sql = "insert into test (tid,date,code,type,type_num,all_num,titime,tutime,tutimestamp) " + "value( ?,?,?,?,?,?,?,?,?) " + “on duplicate key update type_num= ? ,all_num= ? ,titime= ?,tutime= ? ,tutimestamp= ?” ; pstmt = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { Object[] curArgs = args[i]; for (int j = 1; j <= curArgs.length; j++) { pstmt.setObject(j, curArgs[j - 1]); } pstmt.addBatch(); } int[] result = pstmt.executeBatch(); return result; } catch (SQLException ex) { throw new JdbcException(ex); } finally { closeStatement(pstmt); }

jdbc url 写法建议这么写:

jdbc:mysql://127.0.0.1:2883/tpcc?useLocalSessionState=true&allowBatch=true&allowMultiQueries=true&rewriteBatchedStatements=true


mysql租户的 jdbc addBatch功能对insert 是很有好的。可以把 1000个 insert 语句合并成1个insert后面跟1000个values 。而 insert on duplicate update 就没有这个效果。推测主要是这个原因。

其他分析思路就是观察性能了。可以参考:

https://mp.weixin.qq.com/s/9m1qZmnSpo5wuTZvcty56A       https://mp.weixin.qq.com/s/gUBubuHqgxptf4DbdHcGyA







1 个赞

根据1楼的建议调整了 jdbc url。

然后修改了下sql。 发现执行速度快很多,本地 idea跑,1秒3000条。 

String sql = 
		"insert into test (`tid`,`date`,`code`,`type`,`type_num`,`all_num`,`titime`,`tutime`,`tutimestamp`) " +
		"values( ?,?,?,?,?,?,?,?,?) " +
		"on duplicate key update  `type_num` = values(`type_num`) ,`all_num`= values(`all_num`) ,`titime`= values(`titime`),`tutime`= values(`tutime`) ,`tutimestamp`= values(`tutimestamp`) " ;


其他的建议就是加大客户端并发、或者表除了主键和唯一键外的其他索引延迟创建等等。

此外 OB端有些设置也跟性能有关。先有一个性能监控工具,这样好描述和分析性能问题。可以参考:OB 内存分配概述 (qq.com)