方法一,使用PreparedStatement加批量的方法try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(o_url, userName, password);
conn.setAutoCommit(false);
String sql = "INSERT adlogs(ip,website,yyyymmdd,hour,object_id) VALUES(?,?,?,?,?)";
PreparedStatement prest = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
for(int x = 0; x < size; x++){
prest.setString(1, "192.168.1.1");
prest.setString(2, "localhost");
prest.setString(3, "20081009");
prest.setInt(4, 8);
prest.setString(5, "11111111");
prest.addBatch();
}
prest.executeBatch();
conn.commit();
conn.close();
} catch (SQLException ex) {
Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(MyLogger.class.getName()).log(Level.SEVERE, null, ex);
}
说明下在建Statement的时候,后面两个参数的意义:
第一个参数指定 ResultSet 的类型。其选项有:
TYPE_FORWARD_ONLY:缺省类型。只允许向前访问一次,并且不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_INSENSITIVE:允许在列表中向前或向后移动,甚至可以进行特定定位,例如移至列表中的第四个记录或者从当前位置向后移动两个记录。不会受到其他用户对该数据库所作更改的影响。
TYPE_SCROLL_SENSITIVE:象 TYPE_SCROLL_INSENSITIVE 一样,允许在记录中定位。这种类型受到其他用户所作更改的影响。如果用户在执行完查询之后删除一个记录,那个记录将从 ResultSet 中消失。类似的,对数据值的更改也将反映在 ResultSet 中。
第二个参数设置 ResultSet 的并发性,该参数确定是否可以更新 ResultSet。其选项有:
CONCUR_READ_ONLY:这是缺省值,指定不可以更新
ResultSet CONCUR_UPDATABLE:指定可以更新 ResultSet
方法二 使用Statement加批量的方法
conn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
for(int x = 0; x < size; x++){
stmt.addBatch("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");
}
stmt.executeBatch();
conn.commit();
方法三:直接使用Statementconn.setAutoCommit(false);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
for(int x = 0; x < size; x++){
stmt.execute("INSERT INTO adlogs(ip,website,yyyymmdd,hour,object_id) VALUES('192.168.1.3', 'localhost','20081009',8,'23123')");
}
conn.commit();
使用上述方法分别插入10万条数据的平均测试时间为:
方法一:17.844s
方法二:18.421s
方法三:16.359s
可以看出JDBC的batch语句插入不但没有性能提升,反而比没有用batch的时候要慢,当然这可能跟JDBC具体驱动的实现方法有关。 附件中是我测试代码,可以用来在自己电脑上跑一下。
在执行批量插入的时候最主要的是将自动提交取消,这样不管是否用JDBC的batch语法应该都没有关系。
conn.setAutoCommit(false)
个人觉得第一种方法是最方便最实用的。
6
顶
4
踩
分享到:
2008-10-20 16:07
浏览 59997
分类:非技术
评论
4 楼
jurs30
2013-09-03
好东西,多谢楼主分享
3 楼
hzw2312
2012-08-10
费解万分、我也测试了一下、用Hibernate的save方法、一条条的添加
hqlDao.save(customer);
既然比用batch快很多
conn.setAutoCommit(false); //取消自动提交
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
for(int x = 0; x < map.size(); x++){
CustomerManageInfo newinfo = (CustomerManageInfo)map.get(x);
StringBuffer sqlInsert = new StringBuffer();
sqlInsert.append("INSERT INTO CUSTOMERMANAGE_BASICE_INFO ");
//此处set省略......
sqlInsert.append(") ");
stmt.addBatch(sqlInsert.toString());
stmt.executeBatch();
}
try {
conn.commit();
bool = true;
} catch (Exception e1) {
e1.printStackTrace();
conn.rollback();
bool = false;
}
Hibernate用了7秒、batch用了12秒、求解......
2 楼
qq1002517
2012-06-11
我觉得也是。 batch不可能一点效率不提,不然人家开那方法干什么。
1 楼
xifanlou
2008-10-23
弱弱的说一句:
那个...第一个是真正的批更新
后两个只是巧妙的执行了五次假更新,而且看样子是插入的重复数据,没有考虑主键么?
另外,再补充一句:
JDBC只是API,真正的批更新是怎么实现的要看数据库厂商,很多数据库没有更改协议,当执行Batch的时候,其实后台还是走的executeUpdate,是假的
真正的批更新是很牛X的,呵呵,直接插入上万组数据,与非批更新不可同日而语