開發高性能JDBC應用非易事,驅動程序不會因代碼緩慢拋出異常。本文總結經驗證的四大指導原則:正確使用DatabaseMetaData、只獲取所需數據、選用最佳性能功能、妥善管理連接與更新。以下針對常見性能問題提出三大核心技巧。
ResultSet生成的Metadata方法較其他JDBC方法顯著較慢,頻繁調用會拖垮性能。應用程序應緩存getTypeInfo等方法返回的元數據信息,避免重複執行。雖然幾乎所有JDBC應用都用到Metadata,但通過減少調用次數仍可顯著提升性能。一個簡單的Metadata調用可能觸發驅動程序執行複雜甚至多次查詢,這些SQL操作極其消耗資源。
在Metadata方法中使用null參數或搜索模式極其耗時,並增加網絡流量。應盡可能提供非null參數。例如:
// 低效:驅動程序需掃描所有目錄、Schema、表類型
ResultSet rs = conn.getTables(null, null, "WSTable", null);
// 高效:精確指定目錄、Schema、表類型
ResultSet rs = conn.getTables("cat1", "johng", "WSTable", "TABLE");
第一種調用被解釋為「返回任何目錄、任何Schema、任何類型中名為WSTable的對象」;第二種則精確為「返回當前目錄下johng Schema中的表」。驅動程序處理第二種請求效率高得多。已知信息盡量傳遞給驅動程序,能顯著改善性能與可靠性。
為確定表的列特性,避免使用getColumns(),改用預編譯的「啞元查詢」配合getMetaData():
// 案例1:getColumns() —— 發送查詢至數據庫,需獲取N行數據(N=列數)
ResultSet rs = meta.getColumns(null, null, "UnknownTable", null);
while (rs.next()) { String colName = rs.getString(4); ... }
// 案例2:啞元查詢 —— 查詢從不執行,僅預編譯,零網絡開銷
PreparedStatement ps = conn.prepareStatement("SELECT * FROM UnknownTable WHERE 1 = 0");
ResultSetMetaData rsmd = ps.getMetaData();
int colCount = rsmd.getColumnCount();
for (int i = 1; i <= colCount; i++) {
int colType = rsmd.getColumnType(i);
String colName = rsmd.getColumnName(i);
// 直接獲取完整列信息
}
啞元查詢WHERE 1=0確保不返回數據行,僅獲取結果集元數據,極大減少數據庫交互開銷,是獲取表結構的最佳實踐。