Jdbc访问mysql查询聚合函数_JDBC连接参数设置对Oracle数据库的影响分析
一次數(shù)據(jù)庫(kù)性能問題處理引發(fā)的JDBC參數(shù)設(shè)置思考
近期某環(huán)境下系統(tǒng),出現(xiàn)大面積頁面訪問緩慢情況,每個(gè)頁面交易響應(yīng)時(shí)間2-5秒,嚴(yán)重超過平日訪問閾值。
經(jīng)排查分析,問題主要出現(xiàn)在數(shù)據(jù)庫(kù),生成AWR得到32C的數(shù)據(jù)庫(kù)DBtime每小時(shí)采樣達(dá)到4800。進(jìn)一步分析發(fā)現(xiàn)主要等待事件library cache lock,library cache:mutex X。
進(jìn)一步分析發(fā)現(xiàn)DB主要耗時(shí)在SQL解析及解析失敗上。
生成10035事件,發(fā)現(xiàn)數(shù)據(jù)庫(kù)日志中有大量解析失敗錯(cuò)誤,且解析失敗的SQL全部帶有ROWID列。
將該類SQL反饋研發(fā)部門,反饋未在SQL中添加ROWID。那么ROWID是從何而來的呢,查詢相關(guān)資料最后定位到JDBC連接參數(shù)設(shè)置不合理。
那么JDBC連接有哪些參數(shù),各個(gè)參數(shù)作用是什么,參數(shù)設(shè)置會(huì)對(duì)SQL解析產(chǎn)生什么樣的影響呢?帶著這些問題,筆者對(duì)JDBC參數(shù)設(shè)置對(duì)SQL解析影響做了針對(duì)性實(shí)驗(yàn),大家跟著我來一探究竟吧。
JDBC連接參數(shù)說明
JDBC連接數(shù)據(jù)庫(kù)主要有兩個(gè)類分別是PreparedStatement和Statement,兩個(gè)類可以帶三個(gè)參數(shù)分別是:ResultSetType、ResultSetConcurrency、ResultSetHoldability。由于參數(shù)ResultSetConcurrency和ResultSetHoldability對(duì)數(shù)據(jù)庫(kù)連接影響小,且使用限制較多,因此這里重點(diǎn)介紹參數(shù):ResultSetType。
ResultSetType
ResultSetType的可選值有三個(gè),每個(gè)值及對(duì)應(yīng)的作用如下:
ResultSet.TYPE_FORWARD_ONLY:為空時(shí)默認(rèn)值,該值支持結(jié)果集前滾遍歷操作。
ResultSet.TYPE_SCROLL_INSENSITIVE:該值支持結(jié)果集后滾,隨機(jī),取后,取前等操作,當(dāng)其它會(huì)話對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)做出更改時(shí),結(jié)果集不隨之刷新。
ResultSet.TYPE_SCROLL_SENSITIVE:該值支持結(jié)果集后滾,隨機(jī),取后,取前等操作,當(dāng)其它會(huì)話對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)做出更改時(shí),改更會(huì)刷新到本結(jié)果集中,使結(jié)果集中數(shù)據(jù)與數(shù)據(jù)庫(kù)數(shù)據(jù)實(shí)時(shí)一致。
連接參數(shù)測(cè)試
測(cè)試環(huán)境情況如下表:
在測(cè)試數(shù)據(jù)庫(kù)中建表psname,psdept,psobj并插入數(shù)據(jù),表結(jié)構(gòu)如下:
在Oracle中每次程序調(diào)用前清空數(shù)據(jù)庫(kù)緩存(alter system flush shared_pool清空緩存便于觀察SQL執(zhí)行情況),程序調(diào)用結(jié)束后查詢V$SQL視圖,查看解析執(zhí)行的SQL。
參數(shù)設(shè)置對(duì)解析影響
ROWID是Oracle用于查詢表中一行記錄的地址,一旦查詢中出現(xiàn)了SUM,DISTINCT等聚合或去重函數(shù),獲取的數(shù)據(jù)與單行記錄地址不再一一對(duì)應(yīng),因此多表連接、單表查詢帶聚合函數(shù)、數(shù)據(jù)去重等SQL解析過程不會(huì)出現(xiàn)ROWID,如果出現(xiàn)ROWID則會(huì)報(bào)解析錯(cuò)誤。
測(cè)試方法:
設(shè)置JDBC參數(shù)ResultSetType=ResultSet.TYPE_FORWARD_ONLY。
在數(shù)據(jù)庫(kù)服務(wù)端執(zhí)行:alter system set events '10035 trace name context forever,level 1',跟蹤解析SQL。
執(zhí)行程序查看Oracle內(nèi)部視圖V$SQL執(zhí)行解析結(jié)果并截圖。
調(diào)整ResultSetType值為TYPE_SCROLL_SENSITIVE和TYPE_SCROLL_INSENSITIVE重復(fù)1、2步驟執(zhí)行測(cè)試。
比對(duì)不同參數(shù)設(shè)置下Oracle中V$SQL顯示結(jié)果,參數(shù)設(shè)置對(duì)數(shù)據(jù)庫(kù)解析影響。
1)測(cè)試一,單表簡(jiǎn)單SQL1:select ID,NAME from psname。
測(cè)試結(jié)果如下表,執(zhí)行過程后臺(tái)未見解析報(bào)錯(cuò)(如圖3-0),在測(cè)試過程中當(dāng)ResultSetType為TYPE_SCROLL_SENSITIVE時(shí)數(shù)據(jù)庫(kù)執(zhí)行會(huì)自動(dòng)加入rowid列。其中12C給rowid自動(dòng)增加一個(gè)別名(如圖4-1),11G則不會(huì)(如圖4-2)。
圖3-0 10035事件記錄的日志,無錯(cuò)誤輸出
圖3-1 V$SQL查詢的最終執(zhí)行結(jié)果
圖4-1 V$SQL查詢的最終執(zhí)行結(jié)果
圖4-2 V$SQL查詢的最終執(zhí)行結(jié)果
2)測(cè)試二,單表帶聚合函數(shù)或去重SQL語句:
① select ?count(ID) as SUM,dept_id from psname group by dept_id。
② select DISTINCT(OWNER) as OWNER, OBJECT_TYPE FROM TEST001.PSOBJ。
經(jīng)測(cè)試ResultSetType設(shè)置為TYPE_FORWARD_ONLY,TYPE_SCROLL_INSENSITIVE編譯不報(bào)錯(cuò),解析執(zhí)行正常。連接參數(shù)ResultSetType設(shè)置為TYPE_SCROLL_SENSITIVE時(shí),解析會(huì)報(bào)錯(cuò),由于數(shù)據(jù)庫(kù)自身編譯糾錯(cuò)機(jī)制,最終數(shù)據(jù)庫(kù)執(zhí)行結(jié)果正常,該情況測(cè)試結(jié)果如下表:
圖5-1 10035事件記錄的報(bào)錯(cuò)日志
圖5-2 V$SQL查詢的最終執(zhí)行結(jié)果
圖6-1 10035事件記錄的報(bào)錯(cuò)日志
圖6-2 V$SQL查詢的最終執(zhí)行結(jié)果
3)測(cè)試三,表關(guān)聯(lián)查詢SQL3:select
n.id,n.name,d.dept_name from TEST001.PSNAME n ,TEST001.psdept d where n.dept_id=d.dept_id and d.dept_name='Sales'。
經(jīng)測(cè)試ResultSetType設(shè)置為TYPE_FORWARD_ONLY,TYPE_SCROLL_INSENSITIVE編譯不報(bào)錯(cuò),解析執(zhí)行正常。連接參數(shù)ResultSetType設(shè)置為TYPE_SCROLL_SENSITIVE時(shí),解析會(huì)報(bào)錯(cuò),由于數(shù)據(jù)庫(kù)自身編譯糾錯(cuò)機(jī)制,最終數(shù)據(jù)庫(kù)執(zhí)行結(jié)果正常,該情況測(cè)試結(jié)果如下表:
圖7-1 10035事件記錄的報(bào)錯(cuò)日志
圖7-2 V$SQL查詢的最終執(zhí)行結(jié)果
4)測(cè)試四,帶條件全列查詢SQL4:select * from psname where dept_id=2。
經(jīng)測(cè)試ResultSetType設(shè)置為TYPE_FORWARD_ONLY,TYPE_SCROLL_INSENSITIVE編譯不報(bào)錯(cuò),解析執(zhí)行正常。連接參數(shù)ResultSetType設(shè)置為TYPE_SCROLL_SENSITIVE時(shí),解析會(huì)報(bào)錯(cuò),由于數(shù)據(jù)庫(kù)自身編譯糾錯(cuò)機(jī)制,最終數(shù)據(jù)庫(kù)執(zhí)行結(jié)果正常,該情況測(cè)試結(jié)果如下表:
圖8-1 10035事件記錄的報(bào)錯(cuò)日志
圖8-2 V$SQL查詢的最終執(zhí)行結(jié)果
5)結(jié)論:從以上測(cè)試情況看出,當(dāng)ResultSetType等于TYPE_SCROLL_SENSITIVE時(shí),所有SQL編譯過程均會(huì)在查詢結(jié)果集前增加ROWID列。當(dāng)增加ROWID產(chǎn)生語法解析錯(cuò)誤時(shí)(通過10035事件生產(chǎn)的日志可知),數(shù)據(jù)庫(kù)通過內(nèi)部糾錯(cuò)算法得到正確SQL再執(zhí)行,于是在V$SQL表中看到不帶ROWID的正確已執(zhí)行的SQL。當(dāng)JDBC參數(shù)ResultSetType等于TYPE_FORWARD_ONLY,TYPE_SCROLL_INSENSITIVE時(shí)SQL解析都不會(huì)增加ROWID,此兩種情況下SQL執(zhí)行前后完全一致,數(shù)據(jù)庫(kù)日志無解析報(bào)錯(cuò)輸出。
在測(cè)試過程中還通過調(diào)整不同的環(huán)境因素進(jìn)行測(cè)試,發(fā)現(xiàn)數(shù)據(jù)庫(kù)版本、驅(qū)動(dòng)版本、JDK版本對(duì)數(shù)據(jù)庫(kù)解析后ROWID產(chǎn)生無影響,對(duì)比分析如下表:
參數(shù)設(shè)置對(duì)查詢更新數(shù)據(jù)影響
測(cè)試說明:根據(jù)參數(shù)解釋當(dāng)resultSetType為TYPE_SCROLL_SENSITIVE時(shí),查詢結(jié)果集會(huì)隨著數(shù)據(jù)修改動(dòng)態(tài)更新,其他值無此類特性因此此處測(cè)試只測(cè)該情況即可。
測(cè)試過程:
① 設(shè)置JDBC連接參數(shù)ResultSetType=ResultSet.TYPE_SCROLL_SENSITIVE。
② 調(diào)用程序執(zhí)行查詢。
③ 進(jìn)入斷點(diǎn),更新psname表中dept_id字段值。
④ 查看JAVA程序輸出圖,查看數(shù)據(jù)庫(kù)表中結(jié)果值圖,斷點(diǎn)循環(huán)取值時(shí)查看resultset對(duì)應(yīng)ID值。若JAVA輸出結(jié)果集與數(shù)據(jù)庫(kù)查詢一致表明,數(shù)據(jù)動(dòng)態(tài)更新。
測(cè)試結(jié)果如下表:
圖9:JAVA程序輸出結(jié)果
圖10:數(shù)據(jù)庫(kù)查詢結(jié)果
結(jié)論:JDBC連接參數(shù)ResultSetType設(shè)置為TYPE_SCROLL_SENSITIVE均不會(huì)動(dòng)態(tài)更新結(jié)果集。
參數(shù)設(shè)置對(duì)JVM影響
測(cè)試方法:調(diào)整JVM堆大小,查詢數(shù)據(jù)庫(kù)大表結(jié)果集來測(cè)試不同參數(shù)對(duì)查詢結(jié)果集影響。
測(cè)試過程:
① 將JVM大小設(shè)置成-Xmx128m -Xms64m -Xmn32m -Xss16m。
② 執(zhí)行SQL向表PSOBJ插入150萬條數(shù)據(jù),使表數(shù)據(jù)大于128M。
③ 設(shè)置參數(shù)ResultSetType=ResultSet.TYPE_FORWARD_ONLY,程序中執(zhí)行如下查詢:
④ 執(zhí)行程序查看控制臺(tái)輸出結(jié)果并截圖。
⑤ 調(diào)整ResultSetType值為TYPE_SCROLL_SENSITIVE和TYPE_SCROLL_INSENSITIVE重復(fù)1、2步驟執(zhí)行測(cè)試。
測(cè)試結(jié)果如下表:
圖13
圖14
結(jié)論:當(dāng)查詢結(jié)果集大于JVM時(shí),Oracle在ResultSetType為TYPE_FORWARD_ONLY時(shí)正常查詢,其他值時(shí)內(nèi)存異常;MySQL在所有情況下都會(huì)出現(xiàn)內(nèi)存溢出的情況。
JDBC參數(shù)設(shè)置建議
從以上測(cè)試中我們不難發(fā)現(xiàn),由于開發(fā)人員對(duì)JDBC連接參數(shù)設(shè)置不合理,導(dǎo)致了數(shù)據(jù)庫(kù)解析SQL產(chǎn)生大量報(bào)錯(cuò),引起了library cache lock,library cache:mutex X等待事件,造成數(shù)據(jù)庫(kù)性能急劇下降,最終造成業(yè)務(wù)系統(tǒng)響應(yīng)嚴(yán)重超時(shí)。
由此建議JDBC中ResultSetType參數(shù)設(shè)置:若只做一般查詢默認(rèn)值即可;
若需要對(duì)結(jié)果集進(jìn)行遍歷、比較等相關(guān)操作可設(shè)置為TYPE_SCROLL_INSENSITIVE;
不推薦使用TYPE_SCROLL_SENSITIVE,因?yàn)樵搮?shù)不會(huì)動(dòng)態(tài)更新結(jié)果集,且該參數(shù)可能導(dǎo)致數(shù)據(jù)庫(kù)SQL解析錯(cuò)誤而執(zhí)行二次解析消耗數(shù)據(jù)庫(kù)資源;
若查詢結(jié)果集過大,建議使用默認(rèn),避免結(jié)果集過大造成JVM內(nèi)存溢出。
總結(jié)
以上是生活随笔為你收集整理的Jdbc访问mysql查询聚合函数_JDBC连接参数设置对Oracle数据库的影响分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 管理对象是什么_Java工程师
- 下一篇: mysql 一致性读_mysql/mar