JDBC使用MySQL處理大數(shù)據(jù)的時(shí)候,自然而然的想到要使用批處理, 普通的執(zhí)行過程是:每處理一條數(shù)據(jù),就訪問一次數(shù)據(jù)庫(kù); 而批處理是:累積到一定數(shù)量,再一次性提交到數(shù)據(jù)庫(kù),減少了與數(shù)據(jù)庫(kù)的交互次數(shù),所以效率會(huì)大大提高 至于事務(wù):事務(wù)指邏輯上的一組操作,組成這組操作的各個(gè)單元,要不全部成功,要不全部不成功,默認(rèn)是關(guān)閉事務(wù)的。 更多事務(wù)的資料,請(qǐng)參考這里:http://blog.csdn.net/caomiao2006/article/details/22412755
1. PreparedStatement使用批處理 executeBatch()1.1. 不使用executeBatch(),而使用executeUpdate()代碼如下: Class.forName("com.mysql.jdbc.Driver"); for(int i=0; i<10000; i++){ 這樣,更新10000條數(shù)據(jù),就得訪問數(shù)據(jù)庫(kù)10000次 1.2. 而使用executeBatch()代碼如下: Class.forName("com.mysql.jdbc.Driver"); for(int i=0; i<10000; i++){ pstmt.executeBatch();//執(zhí)行批處理
注意:1. 如果使用了 addBatch() -> executeBatch() 還是很慢,那就得使用到這個(gè)參數(shù)了 rewriteBatchedStatements=true (啟動(dòng)批處理操作) 在數(shù)據(jù)庫(kù)連接URL后面加上這個(gè)參數(shù): String dbUrl = "jdbc:mysql://localhost:3306/User? rewriteBatchedStatements=true"; 2. 在代碼中,pstmt的位置不能亂放, //必須放在循環(huán)體外 pstmt = conn.prepareStatement("update content set introtext=? where id=?"); for(int i=0; i<10000; i++){ //放這里,批處理會(huì)執(zhí)行不了,因?yàn)槊看窝h(huán)重新生成了pstmt,不是同一個(gè)了 //pstmt = conn.prepareStatement("update content set introtext=? where id=?"); pstmt.executeBatch();//執(zhí)行批處理 2. 啟用事務(wù)處理Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(dbUrl, user, password); conn.setAutoCommit(false);//將自動(dòng)提交關(guān)閉
3. 事務(wù)和批處理混合使用Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection(dbUrl, user, password); conn.setAutoCommit(false);//將自動(dòng)提交關(guān)閉 for(int i=0; i<1000000; i++){ //每500條執(zhí)行一次,避免內(nèi)存不夠的情況,可參考,Eclipse設(shè)置JVM的內(nèi)存參數(shù) if(i>0 && i%500==0){ //如果不想出錯(cuò)后,完全沒保留數(shù)據(jù),則可以沒執(zhí)行一次提交一次,但得保證數(shù)據(jù)不會(huì)重復(fù) conn.commit(); } } conn.commit();//執(zhí)行完后,手動(dòng)提交事務(wù) 較完整的代碼: ![]() 運(yùn)行結(jié)果: 分別是: 不用批處理,不用事務(wù); 只用批處理,不用事務(wù); 只用事務(wù),不用批處理; 既用事務(wù),也用批處理;(很明顯,這個(gè)最快,所以建議在處理大批量的數(shù)據(jù)時(shí),同時(shí)使用批處理和事務(wù))
|
|