?
??
1
、在客
戶
端
軟
件
開發(fā)
中使用
Thin
驅(qū)動
程序
在 開發(fā) Java 軟 件方面, Oracle 的數(shù)據(jù) 庫 提供了四 種類 型的 驅(qū)動 程序,二 種 用于 應(yīng) 用 軟 件、 applets 、 servlets 等客 戶 端 軟 件,另外二 種 用于數(shù)據(jù) 庫 中的 Java 存 儲過 程等服 務(wù) 器端 軟 件。在客 戶 機(jī)端 軟 件的 開發(fā) 中,我 們 可以 選擇 OCI 驅(qū)動 程序或 Thin 驅(qū)動 程序。 OCI 驅(qū)動 程序利用 Java 本地化接口( JNI ),通 過 Oracle 客 戶 端 軟 件與數(shù)據(jù) 庫進(jìn) 行通 訊 。 Thin 驅(qū)動 程序是 純 Java 驅(qū)動 程序,它直接與數(shù)據(jù) 庫進(jìn) 行通 訊 。 為 了 獲 得最高的性能, Oracle 建 議 在客 戶 端 軟 件的 開發(fā) 中使用 OCI 驅(qū)動 程序, 這 似乎是正確的。但我建 議 使用 Thin 驅(qū)動 程序,因 為 通 過 多次 測試發(fā)現(xiàn) ,在通常情況下, Thin 驅(qū)動 程序的性能都超 過 了 OCI 驅(qū)動 程序。
2 、 關(guān)閉 自 動 提交功能,提高系 統(tǒng) 性能
在第一次建立與數(shù)據(jù) 庫 的 連 接 時 ,在缺省情況下, 連 接是在自 動 提交模式下的。 為 了 獲 得更好的性能,可以通 過調(diào) 用 帶 布 爾 值 false 參數(shù)的 Connection 類 的 setAutoCommit() 方法 關(guān)閉 自 動 提交功能,如下所示:
conn.setAutoCommit(false);
值 得注意的是,一旦 關(guān)閉 了自 動 提交功能,我 們 就需要通 過調(diào) 用 Connection 類 的 commit() 和 rollback() 方法來人工的方式 對 事 務(wù)進(jìn) 行管理。
3 、在 動態(tài) SQL 或有 時間 限制的命令中使用 Statement 對 象
在 執(zhí) 行 SQL 命令 時 ,我 們 有二 種選擇 :可以使用 PreparedStatement 對 象,也可以使用 Statement 對 象。無 論 多少次地使用同一個 SQL 命令, PreparedStatement 都只 對 它解析和 編譯 一次。當(dāng)使用 Statement 對 象 時 , 每 次 執(zhí) 行一個 SQL 命令 時 ,都會 對 它 進(jìn) 行解析和 編譯 。 這 可能會使你 認(rèn)為 ,使用 PreparedStatement 對 象比使用 Statement 對 象的速度更快。然而,我 進(jìn) 行的 測試 表明,在客 戶 端 軟 件中,情況并非如此。 因此,在有 時間 限制的 SQL 操作中,除非成批地 處 理 SQL 命令,我 們應(yīng) 當(dāng)考 慮 使用 Statement 對 象。
此外,使用 Statement 對 象也使得 編 寫 動態(tài) SQL 命令更加 簡單 ,因 為 我 們 可以將字符串 連 接在一起,建立一個有效的 SQL 命令。因此,我 認(rèn)為 , Statement 對 象可以使 動態(tài) SQL 命令的 創(chuàng) 建和 執(zhí) 行 變 得更加 簡單 。
4 、利用 helper 函數(shù) 對動態(tài) SQL 命令 進(jìn) 行格式化
在 創(chuàng) 建使用 Statement 對 象 執(zhí) 行的 動態(tài) SQL 命令 時 ,我 們 需要 處 理一些格式化方面的 問題 。例如,如果我 們 想 創(chuàng) 建一個將名字 O'Reilly 插入表中的 SQL 命令, 則 必 須 使用二個相 連 的 “''” 號替 換 O'Reilly 中的 “'” 號。完成 這 些工作的最好的方法是 創(chuàng) 建一個完成替 換 操作的 helper 方法,然后在 連 接字符串心服用公式表達(dá)一個 SQL 命令 時 ,使用 創(chuàng) 建的 helper 方法。 與此 類 似的是,我 們 可以 讓 helper 方法接受一個 Date 型的 值 ,然后 讓 它 輸 出基于 Oracle 的 to_date() 函數(shù)的字符串表達(dá)式。
5 、利用 PreparedStatement 對 象提高數(shù)據(jù) 庫 的 總 體效率
在使用 PreparedStatement 對 象 執(zhí) 行 SQL 命令 時 ,命令被數(shù)據(jù) 庫進(jìn) 行解析和 編譯 ,然后被放到命令 緩 沖區(qū)。然后, 每 當(dāng) 執(zhí) 行同一個 PreparedStatement 對 象 時 ,它就會被再解析一次,但不會被再次 編譯 。在 緩 沖區(qū)中可以 發(fā)現(xiàn)預(yù)編譯 的命令,并且可以重新使用。在有大量用 戶 的企 業(yè)級應(yīng) 用 軟 件中, 經(jīng) 常會重 復(fù)執(zhí) 行相同的 SQL 命令,使用 PreparedStatement 對 象 帶 來的 編譯 次數(shù)的減少能 夠 提高數(shù)據(jù) 庫 的 總 體性能。如果不是在客 戶 端 創(chuàng) 建、 預(yù)備 、 執(zhí) 行 PreparedStatement 任 務(wù) 需要的 時間長 于 Statement 任 務(wù) ,我會建 議 在除 動態(tài) SQL 命令之外的所有情況下使用 PreparedStatement 對 象。
6 、在成批 處 理重 復(fù) 的插入或更新操作中使用 PreparedStatement 對 象
如果成批地 處 理插入和更新操作,就能 夠顯 著地減少它 們 所需要的 時間 。 Oracle 提供的 Statement 和 CallableStatement 并不真正地支持批 處 理,只有 PreparedStatement 對 象才真正地支持批 處 理。我 們 可以使用 addBatch() 和 executeBatch() 方法 選擇標(biāo) 準(zhǔn)的 JDBC 批 處 理,或者通 過 利用 PreparedStatement 對 象的 setExecuteBatch() 方法和 標(biāo) 準(zhǔn)的 executeUpdate() 方法 選擇 速度更快的 Oracle 專 有的方法。要使用 Oracle 專 有的批 處 理機(jī)制,可以以如下所示的方式 調(diào) 用 setExecuteBatch() :
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}
調(diào) 用 setExecuteBatch() 時 指定的 值 是一個上限,當(dāng)達(dá)到 該值時 ,就會自 動 地引 發(fā) SQL 命令 執(zhí) 行, 標(biāo) 準(zhǔn)的 executeUpdate() 方法就會被作 為 批 處 理送到數(shù)據(jù) 庫 中。我 們 可以通 過調(diào) 用 PreparedStatement 類 的 sendBatch() 方法隨 時傳輸 批 處 理任 務(wù) 。
7 、使用 Oracle locator 方法插入、更新大 對 象( LOB )
Oracle 的 PreparedStatement 類 不完全支持 BLOB 和 CLOB 等大 對 象的 處 理,尤其是 Thin 驅(qū)動 程序不支持利 用 PreparedStatement 對 象的 setObject() 和 setBinaryStream() 方法 設(shè) 置 BLOB 的 值 ,也不支持利用 setCharacterStream() 方法 設(shè) 置 CLOB 的 值 。只有 locator 本身中的方法才能 夠 從數(shù)據(jù) 庫 中 獲 取 LOB 類 型的 值 。可以使用 PreparedStatement 對 象插入或更新 LOB ,但需要使用 locator 才能 獲 取 LOB 的 值 。由于存在 這 二個 問題 ,因此,我建 議 使用 locator 的方法來插入、更新或 獲 取 LOB 的 值 。
8 、使用 SQL92 語 法 調(diào) 用存 儲過 程
在 調(diào) 用 存 儲過 程 時 ,我 們 可以使用 SQL92 或 Oracle PL/SQL ,由于使用 Oracle PL/SQL 并沒有什 么實(shí)際 的好 處 ,而且會 給 以后 維護(hù) 你的 應(yīng) 用程序的 開發(fā) 人 員帶 來麻 煩 ,因此,我建 議 在 調(diào) 用存 儲過 程 時 使用 SQL92 。
9 、使用 Object SQL 將 對 象模式 轉(zhuǎn) 移到數(shù)據(jù) 庫 中
既然可以將 Oracle 的數(shù)據(jù) 庫 作 為 一 種 面向 對 象的數(shù)據(jù) 庫 來使用,就可以考 慮 將 應(yīng) 用程序中的面向 對 象模式 轉(zhuǎn) 到數(shù)據(jù) 庫 中。目前的方法是 創(chuàng) 建 Java bean 作 為偽 裝的數(shù)據(jù) 庫對 象,將它 們 的屬性映射到 關(guān) 系表中,然后在 這 些 bean 中添加方法。盡管 這樣 作在 Java 中沒有什 么問題 ,但由于操作都是在數(shù)據(jù) 庫 之外 進(jìn) 行的,因此其他 訪問 數(shù)據(jù) 庫 的 應(yīng) 用 軟 件無法利用 對 象模式。如果利用 Oracle 的面向 對 象的技 術(shù) ,可以通 過創(chuàng) 建一個新的數(shù)據(jù) 庫對 象 類 型在數(shù)據(jù) 庫 中模仿其數(shù)據(jù)和操作,然后使用 JPublisher 等工具生成自己的 Java bean 類 。如果使用 這種 方式,不但 Java 應(yīng) 用程序可以使用 應(yīng) 用 軟 件的 對 象模式,其他需要共享你的 應(yīng) 用中的數(shù)據(jù)和操作的 應(yīng) 用 軟 件也可以使用 應(yīng) 用 軟 件中的 對 象模式。
10 、利用 SQL 完成數(shù)據(jù) 庫 內(nèi)的操作
我要向大家介 紹 的最重要的 經(jīng)驗 是充分利用 SQL 的面向集合的方法來解決數(shù)據(jù) 庫處 理需求,而不是使用 Java 等 過 程化的 編 程 語 言。
如果 編 程人 員 要在一個表中 查 找 許 多行, 結(jié) 果中的 每 個行都會 查 找其他表中的數(shù)據(jù),最后, 編 程人 員創(chuàng) 建了獨(dú)立的 UPDATE 命令來成批地更新第一個表中的數(shù)據(jù)。與此 類 似的任 務(wù) 可以通 過 在 set 子句中使用多列子 查詢 而在一個 UPDATE 命令中完成。當(dāng)能 夠 在 單 一的 SQL 命令中完成任 務(wù) ,何必要 讓 數(shù)據(jù)在網(wǎng)上流來流去的?我建 議 用 戶認(rèn) 真學(xué) 習(xí) 如何最大限度地 發(fā)揮 SQL 的功能 ?
在 開發(fā) Java 軟 件方面, Oracle 的數(shù)據(jù) 庫 提供了四 種類 型的 驅(qū)動 程序,二 種 用于 應(yīng) 用 軟 件、 applets 、 servlets 等客 戶 端 軟 件,另外二 種 用于數(shù)據(jù) 庫 中的 Java 存 儲過 程等服 務(wù) 器端 軟 件。在客 戶 機(jī)端 軟 件的 開發(fā) 中,我 們 可以 選擇 OCI 驅(qū)動 程序或 Thin 驅(qū)動 程序。 OCI 驅(qū)動 程序利用 Java 本地化接口( JNI ),通 過 Oracle 客 戶 端 軟 件與數(shù)據(jù) 庫進(jìn) 行通 訊 。 Thin 驅(qū)動 程序是 純 Java 驅(qū)動 程序,它直接與數(shù)據(jù) 庫進(jìn) 行通 訊 。 為 了 獲 得最高的性能, Oracle 建 議 在客 戶 端 軟 件的 開發(fā) 中使用 OCI 驅(qū)動 程序, 這 似乎是正確的。但我建 議 使用 Thin 驅(qū)動 程序,因 為 通 過 多次 測試發(fā)現(xiàn) ,在通常情況下, Thin 驅(qū)動 程序的性能都超 過 了 OCI 驅(qū)動 程序。
2 、 關(guān)閉 自 動 提交功能,提高系 統(tǒng) 性能
在第一次建立與數(shù)據(jù) 庫 的 連 接 時 ,在缺省情況下, 連 接是在自 動 提交模式下的。 為 了 獲 得更好的性能,可以通 過調(diào) 用 帶 布 爾 值 false 參數(shù)的 Connection 類 的 setAutoCommit() 方法 關(guān)閉 自 動 提交功能,如下所示:
conn.setAutoCommit(false);
值 得注意的是,一旦 關(guān)閉 了自 動 提交功能,我 們 就需要通 過調(diào) 用 Connection 類 的 commit() 和 rollback() 方法來人工的方式 對 事 務(wù)進(jìn) 行管理。
3 、在 動態(tài) SQL 或有 時間 限制的命令中使用 Statement 對 象
在 執(zhí) 行 SQL 命令 時 ,我 們 有二 種選擇 :可以使用 PreparedStatement 對 象,也可以使用 Statement 對 象。無 論 多少次地使用同一個 SQL 命令, PreparedStatement 都只 對 它解析和 編譯 一次。當(dāng)使用 Statement 對 象 時 , 每 次 執(zhí) 行一個 SQL 命令 時 ,都會 對 它 進(jìn) 行解析和 編譯 。 這 可能會使你 認(rèn)為 ,使用 PreparedStatement 對 象比使用 Statement 對 象的速度更快。然而,我 進(jìn) 行的 測試 表明,在客 戶 端 軟 件中,情況并非如此。 因此,在有 時間 限制的 SQL 操作中,除非成批地 處 理 SQL 命令,我 們應(yīng) 當(dāng)考 慮 使用 Statement 對 象。
此外,使用 Statement 對 象也使得 編 寫 動態(tài) SQL 命令更加 簡單 ,因 為 我 們 可以將字符串 連 接在一起,建立一個有效的 SQL 命令。因此,我 認(rèn)為 , Statement 對 象可以使 動態(tài) SQL 命令的 創(chuàng) 建和 執(zhí) 行 變 得更加 簡單 。
4 、利用 helper 函數(shù) 對動態(tài) SQL 命令 進(jìn) 行格式化
在 創(chuàng) 建使用 Statement 對 象 執(zhí) 行的 動態(tài) SQL 命令 時 ,我 們 需要 處 理一些格式化方面的 問題 。例如,如果我 們 想 創(chuàng) 建一個將名字 O'Reilly 插入表中的 SQL 命令, 則 必 須 使用二個相 連 的 “''” 號替 換 O'Reilly 中的 “'” 號。完成 這 些工作的最好的方法是 創(chuàng) 建一個完成替 換 操作的 helper 方法,然后在 連 接字符串心服用公式表達(dá)一個 SQL 命令 時 ,使用 創(chuàng) 建的 helper 方法。 與此 類 似的是,我 們 可以 讓 helper 方法接受一個 Date 型的 值 ,然后 讓 它 輸 出基于 Oracle 的 to_date() 函數(shù)的字符串表達(dá)式。
5 、利用 PreparedStatement 對 象提高數(shù)據(jù) 庫 的 總 體效率
在使用 PreparedStatement 對 象 執(zhí) 行 SQL 命令 時 ,命令被數(shù)據(jù) 庫進(jìn) 行解析和 編譯 ,然后被放到命令 緩 沖區(qū)。然后, 每 當(dāng) 執(zhí) 行同一個 PreparedStatement 對 象 時 ,它就會被再解析一次,但不會被再次 編譯 。在 緩 沖區(qū)中可以 發(fā)現(xiàn)預(yù)編譯 的命令,并且可以重新使用。在有大量用 戶 的企 業(yè)級應(yīng) 用 軟 件中, 經(jīng) 常會重 復(fù)執(zhí) 行相同的 SQL 命令,使用 PreparedStatement 對 象 帶 來的 編譯 次數(shù)的減少能 夠 提高數(shù)據(jù) 庫 的 總 體性能。如果不是在客 戶 端 創(chuàng) 建、 預(yù)備 、 執(zhí) 行 PreparedStatement 任 務(wù) 需要的 時間長 于 Statement 任 務(wù) ,我會建 議 在除 動態(tài) SQL 命令之外的所有情況下使用 PreparedStatement 對 象。
6 、在成批 處 理重 復(fù) 的插入或更新操作中使用 PreparedStatement 對 象
如果成批地 處 理插入和更新操作,就能 夠顯 著地減少它 們 所需要的 時間 。 Oracle 提供的 Statement 和 CallableStatement 并不真正地支持批 處 理,只有 PreparedStatement 對 象才真正地支持批 處 理。我 們 可以使用 addBatch() 和 executeBatch() 方法 選擇標(biāo) 準(zhǔn)的 JDBC 批 處 理,或者通 過 利用 PreparedStatement 對 象的 setExecuteBatch() 方法和 標(biāo) 準(zhǔn)的 executeUpdate() 方法 選擇 速度更快的 Oracle 專 有的方法。要使用 Oracle 專 有的批 處 理機(jī)制,可以以如下所示的方式 調(diào) 用 setExecuteBatch() :
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}
調(diào) 用 setExecuteBatch() 時 指定的 值 是一個上限,當(dāng)達(dá)到 該值時 ,就會自 動 地引 發(fā) SQL 命令 執(zhí) 行, 標(biāo) 準(zhǔn)的 executeUpdate() 方法就會被作 為 批 處 理送到數(shù)據(jù) 庫 中。我 們 可以通 過調(diào) 用 PreparedStatement 類 的 sendBatch() 方法隨 時傳輸 批 處 理任 務(wù) 。
7 、使用 Oracle locator 方法插入、更新大 對 象( LOB )
Oracle 的 PreparedStatement 類 不完全支持 BLOB 和 CLOB 等大 對 象的 處 理,尤其是 Thin 驅(qū)動 程序不支持利 用 PreparedStatement 對 象的 setObject() 和 setBinaryStream() 方法 設(shè) 置 BLOB 的 值 ,也不支持利用 setCharacterStream() 方法 設(shè) 置 CLOB 的 值 。只有 locator 本身中的方法才能 夠 從數(shù)據(jù) 庫 中 獲 取 LOB 類 型的 值 。可以使用 PreparedStatement 對 象插入或更新 LOB ,但需要使用 locator 才能 獲 取 LOB 的 值 。由于存在 這 二個 問題 ,因此,我建 議 使用 locator 的方法來插入、更新或 獲 取 LOB 的 值 。
8 、使用 SQL92 語 法 調(diào) 用存 儲過 程
在 調(diào) 用 存 儲過 程 時 ,我 們 可以使用 SQL92 或 Oracle PL/SQL ,由于使用 Oracle PL/SQL 并沒有什 么實(shí)際 的好 處 ,而且會 給 以后 維護(hù) 你的 應(yīng) 用程序的 開發(fā) 人 員帶 來麻 煩 ,因此,我建 議 在 調(diào) 用存 儲過 程 時 使用 SQL92 。
9 、使用 Object SQL 將 對 象模式 轉(zhuǎn) 移到數(shù)據(jù) 庫 中
既然可以將 Oracle 的數(shù)據(jù) 庫 作 為 一 種 面向 對 象的數(shù)據(jù) 庫 來使用,就可以考 慮 將 應(yīng) 用程序中的面向 對 象模式 轉(zhuǎn) 到數(shù)據(jù) 庫 中。目前的方法是 創(chuàng) 建 Java bean 作 為偽 裝的數(shù)據(jù) 庫對 象,將它 們 的屬性映射到 關(guān) 系表中,然后在 這 些 bean 中添加方法。盡管 這樣 作在 Java 中沒有什 么問題 ,但由于操作都是在數(shù)據(jù) 庫 之外 進(jìn) 行的,因此其他 訪問 數(shù)據(jù) 庫 的 應(yīng) 用 軟 件無法利用 對 象模式。如果利用 Oracle 的面向 對 象的技 術(shù) ,可以通 過創(chuàng) 建一個新的數(shù)據(jù) 庫對 象 類 型在數(shù)據(jù) 庫 中模仿其數(shù)據(jù)和操作,然后使用 JPublisher 等工具生成自己的 Java bean 類 。如果使用 這種 方式,不但 Java 應(yīng) 用程序可以使用 應(yīng) 用 軟 件的 對 象模式,其他需要共享你的 應(yīng) 用中的數(shù)據(jù)和操作的 應(yīng) 用 軟 件也可以使用 應(yīng) 用 軟 件中的 對 象模式。
10 、利用 SQL 完成數(shù)據(jù) 庫 內(nèi)的操作
我要向大家介 紹 的最重要的 經(jīng)驗 是充分利用 SQL 的面向集合的方法來解決數(shù)據(jù) 庫處 理需求,而不是使用 Java 等 過 程化的 編 程 語 言。
如果 編 程人 員 要在一個表中 查 找 許 多行, 結(jié) 果中的 每 個行都會 查 找其他表中的數(shù)據(jù),最后, 編 程人 員創(chuàng) 建了獨(dú)立的 UPDATE 命令來成批地更新第一個表中的數(shù)據(jù)。與此 類 似的任 務(wù) 可以通 過 在 set 子句中使用多列子 查詢 而在一個 UPDATE 命令中完成。當(dāng)能 夠 在 單 一的 SQL 命令中完成任 務(wù) ,何必要 讓 數(shù)據(jù)在網(wǎng)上流來流去的?我建 議 用 戶認(rèn) 真學(xué) 習(xí) 如何最大限度地 發(fā)揮 SQL 的功能 ?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
