在典型的SQL伺服器性能優化實踐中,我們經常使用JDBC驅動程式來識別哪一位使用者使用的SQL伺服器資源最多。
查詢語句對於常使用JDBC驅動程式的使用者來說並不陌生。

 

SELECT contact FROM tbl_Customers WHERE ID = @P0
這種查詢僅需要3毫秒的時間即可以得到結果,看起來並不是太慢。但在使用這個語句對SQL伺服器進行查詢的時候,已經經歷了數百萬次計算,並且在這個過程中,將限制SQL其他程式運行對資料庫資源的使用。為了瞭解整個運行過程,讓我們看一下這個語句所牽扯到的SQL查詢計劃後臺的運行程式。您會發現,這個過程其實比想像的要複雜許多。(這裡僅提供執行計畫中的最重要的一部分):

 

Nested Loops(Inner Join, OUTER REFERENCES:([Expr1004],
|--Compute Scalar(DEFINE:(([Expr1004],[Expr1005],[Expr1003])=GetRangeThroughConvert([@P0)
| |--Constant Scan
|--Clustered Index Seek(OBJECT:([Prod].[dbo].[tbl_Customers]..[ID].. SEEK:( [ID] >
[Expr1008] AND [ID] < [Expr1009]), WHERE:(CONVERT_IMPLICIT(Nvarchar(255),
[ID],0)=[@P0])
在整個查詢過程中,程式運行了嵌套迴圈。這是對一個檔的單一查找,為何SQL伺服器在編譯查詢計劃是會使用嵌套迴圈程式而不是直接通過索引尋找相應的檔參數值?如果仔細分析一下上面的後臺運行程式,您會發現在上述程式語句中有一個隱形的嵌套迴圈語句:

 

CONVERT_IMPLICIT(Nvarchar(255), [ID],0)
這個語句就是為什麼SQL伺服器會重複引用嵌套程式的原因所在。為了儘量減少用戶端JAVA本地字串之間的轉換,JAVA程式是按照統一碼編寫的。這就使得使用者在使用JDBC驅動程式對SQL伺服器進行查詢或操作時,所有的Varchar()會在預設狀態下變為Nvarchar()變數。而在SQL程式運行中Nvarchar()變數的運行優先順序高於Varchar()變數。SQL伺服器自身並不能將Nvarchar()變數轉換為Varchar()變數,所以執行兩種語句代碼之間的轉換時會發生一些錯誤。如@P0本身是Varchar()變數,但連結傳送給SQL資料庫時會以Nvarchar()變數的形式傳送。
那麼,我們如何使得JDBC驅動程式停止這一轉換呢?在JDBC驅動程式屬性中有一個按照「統一碼字串參數發送連結命令「(sendStringParametersAsUnicode)的選項。在預設狀態下,這個選項的選擇是,我們可以手動的將其改為否。這樣問題就得到了解決。@P0會按照Varchar()變數進行發送,從而不再參與到嵌套迴圈查詢過程中。
如果使用者希望同時傳送Varchar()和Nvarchar()變數時,可以先將「統一碼字串參數發送連結命令」的選項設置為否。另外增加保證Nvarchar()變數傳輸的語句:

 

pStmt.setObject(2,Id,Types.NVARCHAR);
在對連結字串屬性進行修改後,整個過程運行的時間可以由3毫秒縮減為1.5毫秒。總工作量可以提高20%。沒想到吧,一個小小的設置可以帶來那麼大的後臺運行變化。
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()