preparedStatement Batch功能

使用PreparedStatement的Batch功能

Update大量的數據時, 先Prepare一個INSERT語句再多次的執行, 會導致很多次的網絡連接. 要減少JDBC的調用次數改善性能, 你可以使用PreparedStatement的AddBatch()方法一次性發送多個查詢給數據庫. 例如, 讓我們來比較一下下面的例子.

例 1: 多次執行Prepared Statement

PreparedStatement ps = conn.prepareStatement(
   "INSERT into employees values (?, ?, ?)");

for (n = 0; n < 100; n++) {

  ps.setString(name[n]);
  ps.setLong(id[n]);
  ps.setInt(salary[n]);
  ps.executeUpdate();
}

例 2: 使用Batch

PreparedStatement ps = conn.prepareStatement(
   "INSERT into employees values (?, ?, ?)");

for (n = 0; n < 100; n++) {

  ps.setString(name[n]);
  ps.setLong(id[n]);
  ps.setInt(salary[n]);
  ps.addBatch();
}
ps.executeBatch();

在例 1中, PreparedStatement被用來多次執行INSERT語句. 在這裏, 執行了100次INSERT操作, 共有101次網絡往返. 其中,1次往返是預儲statement, 另外100次往返執行每個迭代. 在例2中, 當在100次INSERT操作中使用addBatch()方法時, 只有兩次網絡往返. 1次往返是預儲statement, 另一次是執行batch命令. 雖然Batch命令會用到更多的數據庫的CPU週期, 但是通過減少網絡往返,性能得到提高. 記住, JDBC的性能最大的增進是減少JDBC驅動與數據庫之間的網絡通訊.

 

使用有效的getter方法

JDBC提供多種方法從ResultSet中取得數據, 像getInt(), getString(), 和getObject()等等. 而getObject()方法是最泛化了的, 提供了最差的性能。 這是因爲JDBC驅動必須對要取得的值的類型作額外的處理以映射爲特定的對象. 所以就對特定的數據類型使用相應的方法.

要更進一步的改善性能, 應在取得數據時提供字段的索引號, 例如, getString(1), getLong(2), 和getInt(3)等來替代字段名. 如果沒有指定字段索引號, 網絡交通不會受影響, 但會使轉換和查找的成本增加. 例如, 假設你使用getString("foo") ... JDBC驅動可能會將字段名轉爲大寫(如果需要), 並且在到字段名列表中逐個比較來找到"foo"字段. 如果可以, 直接使用字段索引, 將爲你節省大量的處理時間.

例如, 假設你有一個100行15列的ResultSet, 字段名不包含在其中. 你感興趣的是三個字段 EMPLOYEENAME (字串型), EMPLOYEENUMBER (長整型), 和SALARY (整型). 如果你指定getString(“EmployeeName”), getLong(“EmployeeNumber”), 和getInt(“Salary”), 查詢旱每個字段名必須被轉換爲metadata中相對應的大小寫, 然後才進行查找. 如果你使用getString(1), getLong(2), 和getInt(15). 性能就會有顯著改善.

獲取自動生成的鍵值

有許多數據庫提供了隱藏列爲表中的每行記錄分配一個唯一鍵值. 很典型, 在查詢中使用這些字段類型是取得記錄值的最快的方式, 因爲這些隱含列通常反應了數據在磁盤上的物理位置. 在JDBC3.0之前, 應用程序只可在插入數據後通過立即執行一個SELECT語句來取得隱含列的值.

例如:
//插入行
int rowcount = stmt.executeUpdate (
   "insert into LocalGeniusList (name) values (''Karen'')");
// 現在爲新插入的行取得磁盤位置 - rowid
ResultSet rs = stmt.executeQuery (
   "select rowid from LocalGeniusList where name = ''Karen''");

這種取得隱含列的方式有兩個主要缺點. 第一, 取得隱含列是在一個獨立的查詢中, 它要透過網絡送到服務器後再執行. 第二, 因爲不是主鍵, 查詢條件可能不是表中的唯一性ID. 在後面一個例子中, 可能返回了多個隱含列的值, 程序無法知道哪個是最後插入的行的值.

(譯者:由於不同的數據庫支持的程度不同,返回rowid的方式各有差異。在SQL Server中,返回最後插入的記錄的id可以用這樣的查詢語句:SELECT @IDENTITY )

JDBC3.0規範中的一個可選特性提供了一種能力, 可以取得剛剛插入到表中的記錄的自動生成的鍵值.

例如:
int rowcount = stmt.executeUpdate (
   "insert into LocalGeniusList (name) values (''Karen'')",
// 插入行並返回鍵值
Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys ();
// 得到生成的鍵值

現在, 程序中包含了一個唯一性ID, 可以用來作爲查詢條件來快速的存取數據行, 甚至於表中沒有主鍵的情況也可以.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章