成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iBATIS框架batch處理優(yōu)化淺析

開(kāi)發(fā) 后端
iBATIS框架batch處理優(yōu)化向你介紹iBATIS框架下對(duì)batch處理的優(yōu)化情況。

iBATIS框架batch處理優(yōu)化的情況。為什么要做batch處理這個(gè)問(wèn)題我就不解釋了,因?yàn)槲蚁肽銈兛隙鼙任医忉尩母茫∪绻阏娴牟恢溃蔷偷窖呕⑸先ニ阉饕幌掳?/P>

Oracle回滾段

這個(gè)問(wèn)題偶也不很明白,只是大概有個(gè)了解,如果你是這方面的專家,或者對(duì)這方面有比較深的理解,別忘了跟偶分享哦☻

在JDBC中如何做batch處理

JDBC提供了數(shù)據(jù)庫(kù)batch處理的能力,在數(shù)據(jù)大批量操作(新增、刪除等)的情況下可以大幅度提升系統(tǒng)的性能。我以前接觸的一個(gè)項(xiàng)目,在沒(méi)有采用batch處理時(shí),刪除5萬(wàn)條數(shù)據(jù)大概要半個(gè)小時(shí)左右,后來(lái)對(duì)系統(tǒng)進(jìn)行改造,采用了batch處理的方式,刪除5萬(wàn)條數(shù)據(jù)基本上不會(huì)超過(guò)1分鐘。看一段JDBC代碼:

  1. //關(guān)閉自動(dòng)執(zhí)行  
  2. con.setAutoCommit(false);  
  3. Statementstmt=con.createStatement();  
  4.  
  5. stmt.addBatch("INSERTINTOemployeesVALUES(1000,'JoeJones')");  
  6. stmt.addBatch("INSERTINTOdepartmentsVALUES(260,'Shoe')");  
  7. stmt.addBatch("INSERTINTOemp_deptVALUES(1000,260)");  
  8.  
  9. //提交一批要執(zhí)行的更新命令  
  10. int[]updateCounts=stmt.executeBatch(); 

本例中禁用了自動(dòng)執(zhí)行模式,從而在調(diào)用Statement.executeBatch()時(shí)可以防止JDBC執(zhí)行事務(wù)處理。禁用自動(dòng)執(zhí)行使得應(yīng)用程序能夠在發(fā)生錯(cuò)誤及批處理中的某些命令不能執(zhí)行時(shí)決定是否執(zhí)行事務(wù)處理。因此,當(dāng)進(jìn)行批處理更新時(shí),通常應(yīng)該關(guān)閉自動(dòng)執(zhí)行。

在JDBC2.0中,Statement對(duì)象能夠記住可以一起提交執(zhí)行的命令列表。創(chuàng)建語(yǔ)句時(shí),與它關(guān)聯(lián)的命令列表為空。Statement.addBatch()方法為調(diào)用語(yǔ)句的命令列表添加一個(gè)元素。如果批處理中包含有試圖返回結(jié)果集的命令,則當(dāng)調(diào)用Statement.executeBatch()時(shí),將拋出SQLException。只有DDL和DML命令(它們只返回簡(jiǎn)單的更新計(jì)數(shù))才能作為批處理的一部分來(lái)執(zhí)行。如果應(yīng)用程序決定不提交已經(jīng)為某語(yǔ)句構(gòu)
造的命令批處理,則可以調(diào)用方法Statement.clearBatch()(以上沒(méi)有顯示)來(lái)重新設(shè)置批處理。

Statement.executeBatch()方法將把命令批處理提交給基本DBMS來(lái)執(zhí)行。命令的執(zhí)行將依照在批處理中的添加順序來(lái)進(jìn)行。ExecuteBatch()為執(zhí)行的命令返回更新計(jì)數(shù)數(shù)組。數(shù)組中對(duì)應(yīng)于批處理中的每個(gè)命令都包含了一項(xiàng),而數(shù)組中各元素依據(jù)命令的執(zhí)行順序(這還是和命令的最初添加順序相同)來(lái)排序。調(diào)用executeBatch()將關(guān)閉發(fā)出調(diào)用的Statement對(duì)象的當(dāng)前結(jié)果集(如果有一個(gè)結(jié)果集是打開(kāi)的)。executeBatch()返回后,將重新將語(yǔ)句的內(nèi)部批處理命令列表設(shè)置為空。

如果批處理中的某個(gè)命令無(wú)法正確執(zhí)行,則ExecuteBatch()將拋出BatchUpdateException。可以調(diào)用BatchUpdateException.getUpdateCounts()方法來(lái)為批處理中成功執(zhí)行的命令返回更新計(jì)數(shù)的整型數(shù)組。因?yàn)楫?dāng)有第一個(gè)命令返回錯(cuò)誤時(shí),Statement.executeBatch()就中止,而且這些命令是依據(jù)它們?cè)谂幚碇械奶砑禹樞蚨鴪?zhí)行的。所以如果BatchUpdateException.getUpdateCounts()所返回的數(shù)組包含N個(gè)元素,這就意味著在調(diào)用executeBatch()時(shí)批處理中的前N個(gè)命令被成功執(zhí)行。用PreparedStatement可以象下面這樣寫(xiě)代碼:

  1. //關(guān)閉自動(dòng)執(zhí)行  
  2. con.setAutoCommit(false);  
  3. PreparedStatementstmt=con.prepareStatement("INSERTINTOemployeesVALUES(?,?)");  
  4.  
  5. stmt.setInt(1,2000);  
  6. stmt.setString(2,"KellyKaufmann");  
  7. stmt.addBatch();  
  8. ??? 
  1. //提交要執(zhí)行的批處理  
  2.  
  3. int[]updateCounts=stmt.executeBatch(); 

iBATIS框架對(duì)batch處理優(yōu)化的支持

iBATIS框架對(duì)batch處理提供了很好的支持,底層的實(shí)現(xiàn)方式就是JDBC。下面看一段示例代碼:

  1. privatevoidexecute(SqlMapClientclient){  
  2. if(log.isDebugEnabled()){  
  3. log.debug("executestart...");  
  4. }  
  5.  
  6. client.startBatch();  
  7.  
  8. for(inti=0;i<2000;i++){  
  9.  
  10. client.delete("deletefromorderwhereid=?",i);  
  11.  
  12. }  
  13.  
  14. client.executeBatch();  
  15.  
  16. if(log.isDebugEnabled()){  
  17. log.debug("executeend...");  
  18. }  

iBATIS框架做batch處理的問(wèn)題

在一個(gè)batch中只能對(duì)一個(gè)表進(jìn)行操作,例如插入或刪除。當(dāng)有多個(gè)表需要處理時(shí),只能放在多個(gè)batch中進(jìn)行處理。看下面的一段代碼:

代碼1:

  1. privatevoidexecute(intfrom,intto,Listlist){  
  2. if(log.isDebugEnabled()){  
  3. log.debug("STRGHousekeepTaskexecutestart...");  
  4. }  
  5. HKSqlMapWrappersqlWrapper=HKSqlMapWrapper.newInstance();  
  6. sqlWrapper.startBatch();  
  7.  
  8. for(inti=from;i<to;i++){  
  9. sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));  
  10. sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));  
  11. sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));  
  12. }  
  13. sqlWrapper.execBatch();  
  14. if(log.isDebugEnabled()){  
  15. log.debug("STRGHousekeepTaskexecuteend...");  
  16. }  

這段代碼的目的就是要?jiǎng)h除數(shù)據(jù)庫(kù)中3個(gè)表的數(shù)據(jù),sqlWrapper是iBATIS的SqlMapClient的一個(gè)包裝器,主要是封狀對(duì)事物的控制。當(dāng)批次(既to-from的值)很小的時(shí)候,這樣寫(xiě)是沒(méi)有問(wèn)題的。盡管這段代碼的本意是要享受batch處理帶來(lái)的好處,但是事實(shí)上這段代碼并不會(huì)真正達(dá)到預(yù)期的效果,至于原因,我們一會(huì)在進(jìn)行分析☻。我們先來(lái)看下面一段代碼:

  1. privatevoidexecute(intfrom,intto,Listlist){  
  2. if(log.isDebugEnabled()){  
  3. log.debug("STRGHousekeepTaskexecutestart...");  
  4. }  
  5. HKSqlMapWrappersqlWrapper=HKSqlMapWrapper.newInstance();  
  6. sqlWrapper.startBatch();  
  7.  
  8. for(inti=from;i<to;i++){  
  9. sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR_BL,list.get(i));  
  10. }  
  11. for(inti=from;i<to;i++){  
  12. sqlWrapper.delete(STRGHousekeepConstants.DELETE_STRG_CNTR,list.get(i));  
  13. }  
  14. for(inti=from;i<to;i++){  
  15. sqlWrapper.delete(STRGHousekeepConstants.DELETE_CNTR,list.get(i));  
  16. }  
  17. sqlWrapper.execBatch();  
  18. if(log.isDebugEnabled()){  
  19. log.debug("STRGHousekeepTaskexecuteend...");  
  20. }  

代碼2

正如你所看到的,和代碼1相比它只是做了3次循環(huán),每個(gè)循環(huán)執(zhí)行一個(gè)表的操作。雖然麻煩,但是卻真正的享受到了batch處理的好處!下面是時(shí)候解釋一下這兩段代碼幕后的秘密了☻。
在前面的章節(jié)里已經(jīng)解釋了JDBC如何做batch處理,如果還不清楚的話請(qǐng)查看前面的章節(jié)。要解釋這兩段代碼里面的玄機(jī),還得看一段代碼☻下面的代碼是從iBATIS源碼中提取的:

  1. publicvoidaddBatch(RequestScoperequest,Connectionconn,Stringsql,Object[]parameters){  
  2. PreparedStatementps=null;  
  3. if(currentSql!=null 
  4. &&sql.hashCode()==currentSql.hashCode()  
  5. &&sql.length()==currentSql.length()){  
  6. intlast=statementList.size()-1;  
  7. ps=(PreparedStatement)statementList.get(last);  
  8. }else{  
  9. ps=conn.prepareStatement(sql);  
  10. currentSql=sql;  
  11. statementList.add(ps);  
  12. }  
  13. request.getParameterMap().setParameters(request,ps,parameters);  
  14. ps.addBatch();  
  15. size++;  

這就是iBATIS中batch處理的做法,在這里不想對(duì)這段代碼做一一解釋,有興趣的可以自己查看一下iBATIS的源碼,我們只關(guān)心它如何對(duì)一條語(yǔ)句進(jìn)行處理。參數(shù)sql是要進(jìn)行batch處理的語(yǔ)句,parameters是sql的參數(shù)列表,如果sql和實(shí)例變量currentSql相等,則從statementList列表里面得到一個(gè)PreparedStatement,然后進(jìn)行batch處理,如果不等就新生成一個(gè)PreparedStatement對(duì)象,并把它加到statementList列表里面,并把當(dāng)前sql的值附給currentSql,下次傳遞來(lái)sql的時(shí)候就會(huì)和這個(gè)新的currentSql比較。這就是為什么在一個(gè)循環(huán)里面只對(duì)一個(gè)表進(jìn)行處理的原因了。如果在一個(gè)循環(huán)里面對(duì)多個(gè)表進(jìn)行處理,每次傳給addBatch方法的sql都是新的,都會(huì)生成一個(gè)新的PreparedStatement,所以也就享受不到batch處理帶來(lái)的好處了!

按照代碼1的方式執(zhí)行程序,當(dāng)batchsize很小的時(shí)候盡管享受不到batch處理帶來(lái)的好處,但是也不至于會(huì)出什么大問(wèn)題,但是當(dāng)batchsize值很大的時(shí)候(我在程序中試驗(yàn)過(guò)1000-5000范圍),數(shù)據(jù)庫(kù)就會(huì)報(bào)錯(cuò)了!錯(cuò)誤是"toomanycourses",原因是每生成一個(gè)PreparedStatement實(shí)例,就會(huì)相應(yīng)的生成一個(gè)course。假設(shè)batchsize是5000,要?jiǎng)h除10個(gè)表的數(shù)據(jù),那么產(chǎn)生的course的數(shù)目就是5000*10=50000,這對(duì)數(shù)據(jù)庫(kù)來(lái)說(shuō)是不能接受
的,所以就會(huì)報(bào)錯(cuò)。

如果按照代碼2的的方式寫(xiě)程序肯定是沒(méi)有問(wèn)題的,只會(huì)生成10個(gè)PreparedStatement實(shí)例,相應(yīng)的也只會(huì)生成10個(gè)course,這樣就真正的享受到了batch處理帶來(lái)的好處。但是,作為一名“挑剔”的程序員,我們?cè)趺茨苋萑踢@樣的寫(xiě)法呢?明明一個(gè)循環(huán)就可以搞定,現(xiàn)在要分成10個(gè)循環(huán)來(lái)做,非但效率上存在問(wèn)題,大量重復(fù)的代碼也讓我們的程序顯得很沒(méi)“水準(zhǔn)”。

既然第一種方式不能享受batch處理帶來(lái)的好處,并且還會(huì)出錯(cuò),第二種方式代碼又非常的丑陋,那么我們就得想個(gè)辦法來(lái)解決這個(gè)問(wèn)題了。請(qǐng)記住:解決問(wèn)題的過(guò)程就是一種享受☻。

修改底層代碼,支持多表batch處理.

既然出問(wèn)題的地方找到了,那么解決它就很容易了。什么,你說(shuō)還不知道問(wèn)題出在哪?MyGod!Killme,pleale☻!

在這里分享一下我的思路,把每次傳近來(lái)的sql作為key、把生成的PreparedStatement實(shí)例作為value放在一個(gè)Map里以后每次傳來(lái)sql時(shí)先判斷在Map里有沒(méi)有這個(gè)key,如果有就直接拿到它的value作為PreparedStatement實(shí)例,如果沒(méi)有就新生成一個(gè)PreparedStatement實(shí)例并把它放到Map里。這樣有幾個(gè)sql就有幾個(gè)PreparedStatement實(shí)例,和寫(xiě)多個(gè)循環(huán)效果是一樣的。但寫(xiě)一個(gè)循環(huán)會(huì)更爽!

【編輯推薦】

  1. iBATIS.NET配置六點(diǎn)總結(jié)
  2. iBATIS SQLMap配置Demo淺析
  3. iBATIS參數(shù)理解淺析
  4. iBATIS用法之SqlMapTemplate內(nèi)部類詳解
  5. iBATIS配置類及操作類的淺析
責(zé)任編輯:仲衡 來(lái)源: IT168
相關(guān)推薦

2009-07-24 16:42:46

iBatis框架做ba

2009-07-16 09:14:26

iBATIS DAO

2009-07-15 17:41:55

iBATIS事務(wù)處理

2009-07-20 13:22:47

iBATIS.Net日

2009-07-21 11:12:00

iBATIS配置

2009-07-22 10:42:59

iBATIS Cach

2009-07-15 17:58:07

iBATIS 動(dòng)態(tài)映射

2009-07-16 10:23:30

iBATIS工作原理

2009-07-15 17:19:31

iBATIS Ecli

2009-07-17 10:32:45

iBATIS MapB

2009-07-22 10:03:11

iBATIS Resu

2009-07-20 18:00:16

iBATIS DAO事

2009-07-20 15:14:44

iBATIS.NET連

2009-07-17 10:59:59

iBATIS接口

2009-07-22 16:02:14

iBATIS參數(shù)

2009-07-22 15:01:01

iBATIS SQLM

2009-07-17 09:44:40

iBATIS教程

2009-07-16 13:08:09

iBATIS快速創(chuàng)建應(yīng)

2009-07-22 15:21:00

iBATIS SQLM

2009-07-15 16:42:03

iBATIS讀寫(xiě)CLO
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 亚洲日日夜夜 | 国产精品黄色 | 黄网站在线观看 | 永久免费av | 久久伊人一区二区 | 99久久婷婷 | 精品国产一区二区三区av片 | 伊人久麻豆社区 | 91社区在线高清 | 亚洲综合在线播放 | 欧美日韩国产一区 | 日本天堂视频 | 欧美午夜一区 | 亚洲乱码一区二区三区在线观看 | 99成人免费视频 | 欧美日韩亚洲国产 | 欧美成人免费在线视频 | av网站免费看 | 欧美一级精品片在线看 | 在线小视频 | 国产美女自拍视频 | 日本三级黄视频 | 久久免费香蕉视频 | 国产一区二区在线播放 | 中文字幕在线观看www | 日韩视频一区在线观看 | 欧美一级片久久 | 国产成人99久久亚洲综合精品 | 久久综合国产精品 | 亚洲中国字幕 | 久久高清国产 | 日本三级网址 | 国产精品国产三级国产aⅴ中文 | 男人午夜视频 | 视频一区二区中文字幕 | 日韩成人一区 | 久久99久久99精品免视看婷婷 | 久久综合一区二区三区 | 亚洲成人毛片 | 午夜成人免费视频 | 好婷婷网 |