2017-11-15

[Performance Tuning] Use SqlParameter, specified SqlDbType and length - Avoid Plan Cache Pollution


使用 SqlParameter - Add(String, SqlDbType, Int32) ,請記得指定 資料長度,可以提升效能
  1. 以效能角度來分析,明確指定 資料類型、資料長度,.NET 程式無須額外判斷,節省資源。
  2. 讓 SQL Server 能使用 Parameterization(參數化),重複使用 Execution Plan 的作法, 有效使用系統資源。
  3. 避免發生 Plan Cache Pollution。

.NET 程式使用 4 種不同的方式,以 For 迴圈執行 1,001 次的 SQL 陳述式,彙整如下:

Method Reuse Execution Plan Cache Type Plan Cache(MB) Execution Time(sec)
Hard-Coded SQL No Adhoc 7.8203125 2.5005660
AddWithValue() Partial Prepared 0.28125 0.1603226
Add(String, SqlDbType) - without length Partial Prepared 0.28125 0.1419786
Add(String, SqlDbType, Int32) Yes Prepared 0.070312 0.1399672



SqlParameter - Add(String, SqlDbType, Int32) Method








Demo -
Avoid Plan Cache Pollution - Use SqlParameter, given the specified SqlDbType and size.

示範環境

  • SQL Server 2017 Enterprise Edition
  • VS 2015

A. Hard-Coded SQL Statements

01. Hard-Coded SQL Statements(硬式編碼的 SQL 陳述式) 

以下示範 .NET 應用程式,使用 Hard-Coded SQL 陳述式的方式組合傳入參數值。

  • 使用 For 迴圈執行 SQL 陳述式 1,001 次,每次執行並傳入一個 Hard-Coded 的參數值。
  • 使用 Hard-Coded SQL 傳入參數值 的方式,將使用每一句 SQL 陳述式的 hash value 是不同的,導致 SQL Server 無法重複使用 Execution Plan,必須額外建立各自的 Execution Plan。
  • 在 Plan Cache 裡將存放了 1,001 份不同的 Execution Plan,但其內容卻幾乎相同,而且這是應能重複使用,卻因 hash value 不同而無法重複使用的 Execution Plan。

-- 011_Hard-Coded SQL



02. 觀察 Plan Cache: 各項物件的記憶體使用情況、使用次數等

以本範例來看,使用 Hard-Coded SQL 傳入參數值的作法,產生的副作用是
  • 1,001 份判斷為無法重複使用 Execution Plan,其 Cache Object 都是 Compiled Plan,個別都使用了 8 KB。
  • 每一份 Execution Plan 耗用 8 KB,CacheType 是 Adhoc1,001 份約耗費 7.8203125 MB 的 Plan Cache。

-- 012_View_cache_execution_plan_use_count_total_size




B. SqlParameter - AddWithValue() Method

01. 使用 SqlParameter - AddWithValue() 參數化查詢

以下示範 .NET 應用程式,使用 SqlParameter - AddWithValue() 參數化查詢。

  • 使用 For 迴圈執行 SQL 陳述式 1,001 次,每次執行並傳入一段由 AddWithValue() 所組建的 SQL 陳述式。
  • 使用 AddWithValue(),耗用 .NET 資源去判斷 資料類型、長度等。
  • SQL Server 在編譯由 AddWithValue() 所組建的 SQL 陳述式時,並未能完全有效重複使用。

-- 021_AddWithValue



02. 觀察 Plan Cache: 各項物件的記憶體使用情況、使用次數等

以本範例來看,使用 SqlParameter - AddWithValue() 參數化查詢的作法,SQL Server 已能 初步 採用 Parameterization(參數化) 方式來執行。

優點:
  • 增加關聯式引擎將新的 SQL 陳述式 與 先前編譯之現有 Execution Plan 配對的能力。
  • 重複使用先前 SQL 陳述式 所編譯的 Execution Plan。

整理 Parameterization(參數化) 執行的方式

Parameter Value Parameter Data Types Use Counts Obj Type
1~9 @ctn1 nvarchar(1) 9 Prepared
10~99 @ctn1 nvarchar(2) 90 Prepared
100~999 @ctn1 nvarchar(3) 900 Prepared
1000~1001 @ctn1 nvarchar(4) 2 Prepared

缺點:

  • 執行 1,001 次,SQL Server 依據傳入的資料類型、資料長度,分類為 4 種:nvarchar(1), nvarchar(2), nvarchar(3), nvarchar(4),編譯為 4 種不同的 Execution Plan。
  • 這 1,001 份 SQL 陳述式,分類為這 4 種參數,並且 初步 能重複使用這些先前 所編譯的 Execution Plan。
  • 每一份 Execution Plan 耗用 72 KB,CacheType 是 Prepared4 份約耗費 0.28125 MB 的 Plan Cache。Avg Use Count 是 250 次。

-- 022_View_cache_execution_plan_use_count_total_size




C. SqlParameter - Add(String, SqlDbType) - without length

01. 使用 SqlParameter - Add(String, SqlDbType) 參數化查詢,但 不 指定資料長度

以下示範 .NET 應用程式,使用 SqlParameter - Add(String, SqlDbType) 參數化查詢。

  • 使用 For 迴圈執行 SQL 陳述式 1,001 次,每次執行並傳入一段由 Add(String, SqlDbType) 所組建的 SQL 陳述式。
  • 使用 Add(String, SqlDbType),耗用 .NET 資源去判斷 資料長度等。
  • SQL Server 在編譯由 Add(String, SqlDbType) 所組建的 SQL 陳述式時,並未能 完全有效重複使用。

-- 031_Add_SqlDbType


02. 觀察 Plan Cache: 各項物件的記憶體使用情況、使用次數等

以本範例來看,使用 SqlParameter - Add(String, SqlDbType) 參數化查詢的作法,SQL Server 已能 初步 採用 Parameterization(參數化) 方式來執行。

在 Plan Cache 的使用上,與 B. AddWithValue() Method 相同。

-- 032_View_cache_execution_plan_use_count_total_size




D. SqlParameter - Add(String, SqlDbType, Int32)

01. 使用 SqlParameter - Add(String, SqlDbType, Int32) 參數化查詢,明確指定 資料長度

以下示範 .NET 應用程式,使用 SqlParameter - Add(String, SqlDbType, Int32) 參數化查詢。

  • 使用 For 迴圈執行 SQL 陳述式 1,001 次,每次執行並傳入一段由 Add(String, SqlDbType, Int32) 所組建的 SQL 陳述式。
  • 使用 Add(String, SqlDbType, Int32),已事先指定 資料類型、資料長度無須耗用  .NET 資源去判斷。
  • SQL Server 在編譯由 Add(String, SqlDbType, Int32) 所組建的 SQL 陳述式時,能有效使用 Parameterization(參數化) 來重複執行。


-- 041_Add_SqlDbType_Int32


02. 觀察 Plan Cache: 各項物件的記憶體使用情況、使用次數等

以本範例來看,使用 SqlParameter - Add(String, SqlDbType, Int32) 參數化查詢 的作法,SQL Server 能有效採用 Parameterization(參數化) 方式來執行。

優點:
  • 增加關聯式引擎將新的 SQL 陳述式 與 先前編譯之現有 Execution Plan 配對的能力。
  • 重複使用先前 SQL 陳述式 所編譯的 Execution Plan。

整理 Parameterization(參數化) 執行的方式

Parameter ValueParameter Data TypesUse CountsObj Type
1~1001@ctn1 nvarchar(25)1001Prepared

分析
  • 執行 1,001 次,由於 .NET 已事先定義好 資料類型、資料長度是 nvarchar(25),SQL Server 僅需編譯 1 份 Execution Plan。
  • 這 1,001 份 SQL 陳述式,能重複使用先前 所編譯的 Execution Plan。
  • 這 1 份 Execution Plan 耗用 72 KB,CacheType 是 Prepared,這 1 份約耗費 0.070312 MB 的 Plan Cache。Avg Use Count 是 1,001 次。

-- 042_View_cache_execution_plan_use_count_total_size




彙總分析

使用 SqlParameter - Add(String, SqlDbType, Int32) ,請記得指定 資料長度,可以 提升效能
  1. 以效能角度來分析,明確指定 資料類型、資料長度,.NET 無須額外判斷,節省資源。
  2. 讓 SQL Server 能使用 Parameterization(參數化),重複使用 Execution Plan 的作法, 有效使用系統資源。
  3. 避免發生 Plan Cache Pollution。

.NET 程式使用 4 種不同的方式,以 For 迴圈執行 1,001 次的 SQL 陳述式,彙整如下:

Method Reuse Execution Plan Cache Type Plan Cache(MB) Execution Time(sec)
Hard-Coded SQL No Adhoc 7.8203125 2.5005660
AddWithValue() Partial Prepared 0.28125 0.1603226
Add(String, SqlDbType) - without length Partial Prepared 0.28125 0.1419786
Add(String, SqlDbType, Int32) Yes Prepared 0.070312 0.1399672


-- 101_Application_Summary





SSMS 檢視資料表的資料類型、長度

-- 111_SSMS_Table_Data_Type_Size







範例程式碼

20171114_Avoid Plan Cache Pollution

https://drive.google.com/drive/folders/1h_f32oYgR8ui53hMSz9tUUsd1iql-IdD?usp=sharing





參考資料

Plan cache pollution or how important it is to properly define parameters in code
https://blogs.msdn.microsoft.com/ivandonev/plan-cache-pollution-or-how-important-it-is-to-properly-define-parameters-in-code/

SqlParameterCollection.Add Method
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.add.aspx

SqlParameterCollection.AddWithValue Method (String, Object)
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparametercollection.addwithvalue(v=vs.110).aspx

Plan Caching and Recompilation in SQL Server 2012
https://msdn.microsoft.com/en-us/library/dn148262.aspx

Simple Parameterization
https://technet.microsoft.com/en-us/library/ms186219(v=sql.105).aspx

[SQL Server] Plan Cache concepts - 認識 Plan Cache
http://sharedderrick.blogspot.tw/2017/11/sql-server-plan-cache-concepts-plan.html

[SQL Server] Enable optimize for ad hoc workloads , 針對特定工作負載最佳化
http://sharedderrick.blogspot.tw/2017/11/sql-server-enable-optimize-for-ad-hoc.html

[SQL Server] Ad hoc Query and Reuse - 重複使用
http://sharedderrick.blogspot.tw/2017/11/sql-server-ad-hoc-query-and-reuse.html

[SQL Server] Plan Cache Pollution - Hard-Coded SQL
http://sharedderrick.blogspot.tw/2017/11/sql-server-plan-cache-pollution-hard.html

沒有留言:

張貼留言