最近開發項目使用了Oracle,根據總體架構一開始選擇使用Mybatis,發現核心模塊用Mybatis效率不夠,切換到jdbc實現,效率大增。Oracle可是個龐然大物,特性多多,絲毫不能馬虎,否則很多雷等着去踩。現在產品試運行階段,回頭總結一下踩過的雷,以后有新的發現會持續更新。
1、關於ROWNUM關鍵字
Oracle返回的某條記錄的ROWNUM並不是不變的,不要依賴於ROWNUM,非要依賴ROWNUM,注意添加ORDER BY分支確定ROWNUM確保不同分頁的數據不會重復。項目一啟動就制訂了約束:不能在項目中應用GROUP BY關鍵字。項目中一次需要匯總統計的輸入表達到幾百萬的數據量級,匯總出來輸出最多幾萬條記錄,因此采用分頁查詢,對分頁數據開啟多個線程並行執行計算,做完匯總統計再刪除多有輸入數據,一開始分頁查詢只用了ROWNUM分頁,偶然性的發生匯總出來的數據比輸入數據大的情況,接着定位到了是某些記錄重復進行匯總統計導致。查了Oracle的官方文檔,文檔描述ROWNUM是在查詢返回來的時候決定值,但不是每次查詢相同記錄都是相同的ROWNUM,可能同一條記錄第一次查詢,ROWNUM在1-1000之間,下次查詢在1001-2000之間。解決方案:在查詢語句中加入ORDER BY ID,其中ID是唯一的,重復統計問題得到解決。
2、關於熱塊競爭問題
一張四五百萬級別的輸入表INPUT1關聯查找另一張一千萬級別的輸入表INPUT2,關聯查詢使用了索引,執行計划顯示查詢確實走了索引。一開始從INPUT1獲取n條記錄,對n分成k份,開啟k個線程對k份數據並發處理,線程內部一進來就執行關聯查詢,通過日志得知,查詢時而執行的很慢,DBA協調定位,發現並發查詢的多個線程之間有相同數據分布在一個塊中,導致資源等待。解決方案:在關聯查詢的地方做同步塊處理,即應用關鍵字synchronized將關聯查詢包起來。
3、關於共享內存超出限制問題
利用Mybatis實現跑批插入,INSERT INTO TB_XXX SELECT XX... FROM (SELECT ... FROM DUAL UNION ALL SELECT ... FROM DUAL),子查詢中UNION ALL了1000條記錄,在開發庫和測試庫上執行這條語句正常執行,在生產庫中執行了一段時間后,開始拋出共享內存不足異常信息,原來DBA對開發庫和測試庫沒有設置共享內存限制,生產庫設置了共享內存限制。解決方案:把1000改成了100,暫時問題解決了。