精华帖 (0) :: 良好帖 (4) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2011-05-05
这帮人是不是闲得蛋疼?老是拿这种没有可比性的东西说七说八的,有意思么?
|
|
返回顶楼 | |
发表时间:2011-05-05
railway 写道 你的表格能说明下什么意思吗?看不太明白,那个J/30、J/50、State/30、State/50、H/30、H/50代表什么?数据库连接?
打个比方, jdbc 连, 一种是使用 addbatch 的方法, 将每一条数据添加至 batch 里面来, 当达到一个数据量的时候, 一次提交至数据库. 这里的 30 / 50 就是这意思. 而 statement 的意思则是说拼 SQL 语句, 如 insert into XXX(id, version) values ('', ''),('', '').... 这样可以将多条数据拼接在一起, 执行的时候会一次插入至数据库, 应该说这种方式是效率最快的. Hibernate 30 50 意思一样. 具体可以看看代码 |
|
返回顶楼 | |
发表时间:2011-05-05
snow0613 写道 这帮人是不是闲得蛋疼?老是拿这种没有可比性的东西说七说八的,有意思么?
我说过, 如果效率在一个可以接受的地步, 我想我会选择 Hibernate 而非 jdbc, 只是这样... |
|
返回顶楼 | |
发表时间:2011-05-05
最后修改:2011-05-05
再说,每种技术都有其适用场景,就跟拿Java和.NET啥的比一样,有意义么?另外,批量操作数据的应用不是没有,但在常用的开发中我想应该不多吧?而且这种数量级的操作,你用JDBC一样也会有性能问题,如果是关系型数据库,建议用存储过程;当然更好的选择是用nosql中比较成熟的产品。这取决于你们的架构师。
记住,别老拿性能说事,看着烦~ |
|
返回顶楼 | |
发表时间:2011-05-05
snow0613 写道 再说,每种技术都有其适用场景,就跟拿Java和.NET啥的比一样,有意义么?另外,批量操作数据的应用不是没有,但在常用的开发中我想应该不多吧?而且这种数量级的操作,你用JDBC一样也会有性能问题,如果是关系型数据库,建议用存储过程;当然更好的选择是用nosql中比较成熟的产品。这取决于你们的架构师。
记住,别老拿性能说事,看着烦~ 引用 点快了, 本想发到博客, 却发到论坛了. 主要是坛子里喷的人太多, 只添乱却很少提啥建设性的意见...
呵呵, 总会有那么一些人想要喷几句... |
|
返回顶楼 | |
发表时间:2011-05-05
snow0613 写道 再说,每种技术都有其适用场景,就跟拿Java和.NET啥的比一样,有意义么?另外,批量操作数据的应用不是没有,但在常用的开发中我想应该不多吧?而且这种数量级的操作,你用JDBC一样也会有性能问题,如果是关系型数据库,建议用存储过程;当然更好的选择是用nosql中比较成熟的产品。这取决于你们的架构师。
记住,别老拿性能说事,看着烦~ "当然更好的选择是用nosql中比较成熟的产品." 你用过吗? |
|
返回顶楼 | |
发表时间:2011-05-05
在你的架构下,建议使用hibernate
|
|
返回顶楼 | |
发表时间:2011-05-06
如果上到百万、千万、亿级别的数量时,性能会很明显,原生jdbc比hibernate好,用hibernate要一小时的数据量,用原生jdbc十分钟就可以了。
另外,当这么大(百万级别以上)的数据量时,Oracle要比MS Server好很多。 mysql就更不用说了。 |
|
返回顶楼 | |
发表时间:2011-05-07
liu.anxin 写道 railway 写道 你的表格能说明下什么意思吗?看不太明白,那个J/30、J/50、State/30、State/50、H/30、H/50代表什么?数据库连接?
打个比方, jdbc 连, 一种是使用 addbatch 的方法, 将每一条数据添加至 batch 里面来, 当达到一个数据量的时候, 一次提交至数据库. 这里的 30 / 50 就是这意思. 而 statement 的意思则是说拼 SQL 语句, 如 insert into XXX(id, version) values ('', ''),('', '').... 这样可以将多条数据拼接在一起, 执行的时候会一次插入至数据库, 应该说这种方式是效率最快的. Hibernate 30 50 意思一样. 具体可以看看代码 就我的测试来看,PreparedStatement 和 拼装的SQL性能差距巨大,性能差别可以达到100倍. 测试环境: 服务器:E7300,3G,win2003 R2 SP2,Oracle11R2 客户端:一般100M网络与服务器连接,jdbc驱动ojdbc6 测试结果 测试:数据长度[100],每10提交一次 第一步清理耗时:140ms 第一次一般提交耗时:130ms 第二步清理耗时:0ms 第一次Prepared提交耗时:70ms 第二步清理耗时:0ms 第二次Prepared提交耗时:20ms 第三步清理耗时:0ms 第二次一般提交耗时:100ms ----------------------------------------------- 测试:数据长度[1000],每100提交一次 第一步清理耗时:0ms 第一次一般提交耗时:1140ms 第二步清理耗时:10ms 第一次Prepared提交耗时:40ms 第二步清理耗时:10ms 第二次Prepared提交耗时:40ms 第三步清理耗时:10ms 第二次一般提交耗时:850ms ----------------------------------------------- 测试:数据长度[10000],每1000提交一次 第一步清理耗时:20ms 第一次一般提交耗时:10540ms 第二步清理耗时:80ms 第一次Prepared提交耗时:80ms 第二步清理耗时:80ms 第二次Prepared提交耗时:60ms 第三步清理耗时:80ms 第二次一般提交耗时:10530ms ----------------------------------------------- 测试:数据长度[100000],每1000提交一次 第一步清理耗时:80ms 第一次一般提交耗时:109780ms 第二步清理耗时:750ms 第一次Prepared提交耗时:660ms 第二步清理耗时:830ms 第二次Prepared提交耗时:600ms 第三步清理耗时:1970ms 第二次一般提交耗时:109800ms ----------------------------------------------- public class test { public static Connection cn; static { try { Class.forName("oracle.jdbc.OracleDriver"); cn = DriverManager.getConnection//隐去 } catch (SQLException ex) { Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); } catch (ClassNotFoundException ex) { Logger.getLogger(test.class.getName()).log(Level.SEVERE, null, ex); } } public static void main(String[] args) throws SQLException { cn.setAutoCommit(false); test(100, 10); test(1000, 100); test(10000, 1000); test(100000, 1000); cn.close(); } static void test(int count, int commitlength) throws SQLException { System.out.println("测试:数据长度[" + count + "],每" + commitlength + "提交一次"); Long d1 = System.currentTimeMillis(); clear(); Long d2 = System.currentTimeMillis(); updateString(count, commitlength); Long d3 = System.currentTimeMillis(); clear(); Long d4 = System.currentTimeMillis(); updatePrepared(count, commitlength); Long d5 = System.currentTimeMillis(); clear(); Long d6 = System.currentTimeMillis(); updatePrepared(count, commitlength); Long d7 = System.currentTimeMillis(); clear(); Long d8 = System.currentTimeMillis(); updateString(count, commitlength); Long d9 = System.currentTimeMillis(); System.out.println("第一步清理耗时:" + (d2 - d1) + "ms"); System.out.println("第一次一般提交耗时:" + (d3 - d2) + "ms"); System.out.println("第二步清理耗时:" + (d4 - d3) + "ms"); System.out.println("第一次Prepared提交耗时:" + (d5 - d4) + "ms"); System.out.println("第二步清理耗时:" + (d6 - d5) + "ms"); System.out.println("第二次Prepared提交耗时:" + (d7 - d6) + "ms"); System.out.println("第三步清理耗时:" + (d8 - d7) + "ms"); System.out.println("第二次一般提交耗时:" + (d9 - d8) + "ms"); System.out.println("-----------------------------------------------"); } static void updateString(int count, int commitlength) throws SQLException { String sqlhead = "insert into ZH(zh,product,state) values"; Statement stmt = cn.createStatement(); int k = 0; for (int i = 0; i < count; i++) { k++; String zh = "zh" + i; String pro = "pro" + i; String state = "state" + i; StringBuilder sb = new StringBuilder(); sb.append(sqlhead).append(" ('").append(zh).append("','").append(pro).append("','").append(state).append("')"); stmt.addBatch(sb.toString()); if (k > commitlength) { k = 0; stmt.executeBatch(); cn.commit(); } } stmt.executeBatch(); cn.commit(); stmt.close(); } static void updatePrepared(int count, int commitlength) throws SQLException { PreparedStatement pstmt = cn.prepareStatement("insert into ZH(zh,product,state) values (?,?,?)"); int k = 0; for (int i = 0; i < count; i++) { k++; String zh = "zh" + i; String pro = "pro" + i; String state = "state" + i; pstmt.setString(1, zh); pstmt.setString(2, pro); pstmt.setString(3, state); pstmt.addBatch(); if (k > commitlength) { k = 0; pstmt.executeBatch(); cn.commit(); pstmt.clearBatch(); } } pstmt.executeBatch(); cn.commit(); pstmt.close(); } static void clear() throws SQLException { String sqlhead = "delete from ZH"; Statement stmt = cn.createStatement(); stmt.executeUpdate(sqlhead); cn.commit(); stmt.close(); } } |
|
返回顶楼 | |
发表时间:2011-05-08
darklighting_he 写道 就我的测试来看,PreparedStatement 和 拼装的SQL性能差距巨大,性能差别可以达到100倍. 测试环境: 服务器:E7300,3G,win2003 R2 SP2,Oracle11R2 客户端:一般100M网络与服务器连接,jdbc驱动ojdbc6 测试结果 测试:数据长度[100],每10提交一次 第一步清理耗时:140ms 第一次一般提交耗时:130ms 第二步清理耗时:0ms 第一次Prepared提交耗时:70ms 第二步清理耗时:0ms 第二次Prepared提交耗时:20ms 第三步清理耗时:0ms 第二次一般提交耗时:100ms ----------------------------------------------- 测试:数据长度[1000],每100提交一次 第一步清理耗时:0ms 第一次一般提交耗时:1140ms 第二步清理耗时:10ms 第一次Prepared提交耗时:40ms 第二步清理耗时:10ms 第二次Prepared提交耗时:40ms 第三步清理耗时:10ms 第二次一般提交耗时:850ms ----------------------------------------------- 测试:数据长度[10000],每1000提交一次 第一步清理耗时:20ms 第一次一般提交耗时:10540ms 第二步清理耗时:80ms 第一次Prepared提交耗时:80ms 第二步清理耗时:80ms 第二次Prepared提交耗时:60ms 第三步清理耗时:80ms 第二次一般提交耗时:10530ms ----------------------------------------------- 测试:数据长度[100000],每1000提交一次 第一步清理耗时:80ms 第一次一般提交耗时:109780ms 第二步清理耗时:750ms 第一次Prepared提交耗时:660ms 第二步清理耗时:830ms 第二次Prepared提交耗时:600ms 第三步清理耗时:1970ms 第二次一般提交耗时:109800ms ----------------------------------------------- 注意看你的代码, 你这样比较并不公平. 而且, 很显然, 你并没有明白我的意思. 我再说一下 addbatch 和 statement 两者的区别(主要是指针对上面两个例子来说的). 你的两个例子其实都是用的 addbatch! 只是其中一种使用的直接拼接, 而另一种是用的 预编译 的方式. 使用预编译, 在第一次运行的时候会耗费大量的时间, 它的性能体现在后面的重复执行. 当一条 SQL 语句, 只在每次执行时的值不同时, 使用 预编译无疑是很快的. 但是, 我说的 statment 并不是这个意思! 我说的意思是这样: 拼接 SQL, 将多个数值拼成一条 SQL 进行执行, 如 insert into XXX(id, version) values ('', ''),('', ''),('', ''),('', ''),('', '')..., 这里拼出来的只有一条 SQL, 但将这条语句放入 db 去执行, 会插入多条数据. 这一点不难想像, 其效率远比 addbatch 要快 // 从开始到最后, 我只有这一个 StringBuilder 对象, 每次生成一条SQL, 数据库执行时却插入了多条, 然后又开始拼接 SQL... StringBuilder sql = new StringBuilder(); String str = "INSERT INTO T_USERINFO(CREATE_TIME, ID) VALUES "; sql.append(str); for (int i = 1; i < (num + 1); i++) { // 要保证公平, 也在循环中 new 对象 user = new UserInfo(); sql.append("('").append(user.getCreateTime()); sql.append("', '"); sql.append(user.getId()).append("'),"); if (i % 50 == 0) { // 执行并提交至数据库. 只执行一条 SQL, 结果却会在数据库插入多条数据. // 并没有使用 addbatch! addbatch 时使用预编译, 这一点我还是知道的... st.execute(sql.deleteCharAt(sql.length() - 1).toString()); conn.commit(); // 重新开始拼接字符串 sql.delete(str.length(), sql.length()); } } st.execute(sql.deleteCharAt(sql.length() - 1).toString()); conn.commit(); |
|
返回顶楼 | |