我必須改進一些從Java程序調用Oracle存儲過程的代碼。目前代碼真的非常慢:在我的開發機器上高達大約8秒鐘。在同一臺機器上,如果我直接調用一個執行相同處理並返回相同數據的SQL查詢,則需要100 ms ...爲什麼從Oracle存儲過程中檢索ResultSet非常慢?
該代碼創建一個CallableStatement,將輸出參數之一註冊爲用Oracle光標,然後使用檢索語句的getObject方法光標和解析它的ResultSet:
cstmt = conn.prepareCall("{ call PKG_ESPECEW.P_ListEspece(?, ?, ?, ?, ?, ?) }");
cstmt.registerOutParameter(4, oracle.jdbc.OracleTypes.CURSOR);
[...]
cstmt.executeQuery();
rs = (ResultSet)cstmt.getObject(4);
rs.setFetchSize(1000); //supposed to help ?
options = new HashMap<String, String>(1000);
rs.next() //added that to measure exactly the length of the first call
while(rs.next()) {
[...]
}
我把一些時間戳的代碼知道哪個部分佔用了這麼久。結果:第一次撥打rs.next()
需要幾秒鐘的時間。結果集是平均值,從10到幾千行。正如我之前所說的,處理來自普通PreparedStatement的類似結果集取決於大小需要10-100 ms。
代碼有什麼問題嗎?我如何改進它?如果我沒有任何其他解決方案,我會直接在SQL中執行SQL,但是我更喜歡使用不允許重寫所有過程的解決方案!
這裏是存儲過程的定義:
PROCEDURE P_ListEspece(P_CLT_ID IN ESPECE.ESP_CLT_ID%TYPE, -- Langue de l'utilisateur
P_ESP_GROUP_CODE IN ESPECE.ESP_CODE%TYPE,-- Code du groupe ou NULL
P_Filter IN VARCHAR2, -- Filtre de la requête
P_Cursor OUT L_CURSOR_TYPE, -- Curseur
P_RecordCount OUT NUMBER, -- Nombre d'enregistrement retourne
P_ReturnStatus OUT NUMBER); -- Code d'erreur
有沒有你不使用'OracleCallableStatement的理由。getCursor'而不是'getObject'? – 2010-05-27 15:31:25
我必須將CallableStatement強制轉換爲OracleCallableStatement,但我使用的是DBCP,而CallableStatement實際上是DBCP提供的「代理」,所以我會得到一個異常(我試過了)。 – 2010-05-27 15:47:50
對於抓取,要通過網絡進行優化,您應該使用setRowPrefetch。這產生了巨大的影響。雖然setFetchSize約爲20-30%,但在大型數據集上預取可高達10倍。 – zhrist 2016-08-11 11:44:12