原文:
sql server裡簡單引數化的痛苦
在今天的文章裡,我想談下對於即席sql語句(ad-hoc sql statements),sql server使用的簡單引數化(****** parameterization)的一些特性和***。首先,如果你的sql語句包含這些,簡單引數化不會發生:
一般來說,如果你處理所謂的安全執行計畫(safe execution plan),sql server自動引數化你的sql語句:不管提供的引數值,查詢總必須通向一樣的執行計畫。如果你的執行計畫裡有書籤查詢,這就是不可能的例子。因為臨界點定義了是否進行書籤查詢還是全表/聚集索引掃瞄。
如果sql server能自動引數化你的sql語句,你還是要考慮下sql server引入的自動引數化sql語句的一些***。我們來看乙個具體的例子。下列查詢建立乙個表,執行乙個會被sql server自動引數化的簡單sql語句。
1然後當你檢視計畫快取時,你會看到sql server能為你自動引數化sql語句:--create a ****** table
2create
table
orders3(
4 col1 int
identity(1, 1) primary
keynot
null
,5 price decimal(18, 2)6
)7go8
9--this query gets auto parametrized, because it is a ****** query with a safe (consistent) plan
10select
*from
orders
11where price =
5.70
12go
1314
--analyze the plan cache
15select
16 st.text
, 17
qs.execution_count,
18cp.cacheobjtype,
19cp.objtype,
20 cp.*
,21 qs.*
, 22 p.*
23from
sys.dm_exec_cached_plans cp
24cross
25cross
26left
join sys.dm_exec_query_stats qs on qs.plan_handle =
cp.plan_handle
27where st.text
like
'%orders%'28
go
(@1 numeric(3,2))select * from [orders] where [price]=@1但什麼是選擇的作為引數的資料型別?最小可能的那個!在這裡是numeric(3,2)!如果現在你執行下列2個查詢:
1sql server能重用為第1個使用8.7值sql語句的引數化sql語句的執行計畫。但用124.50值的第2個sql語句呢?對於這個sql語句快取的計畫不能被重用,因為124.50值不符合numeric(3,2)。在這個情況下,sql server用numeric(5,2)資料型別生成你sql語句的新引數化版本。你剛用你的sql語句的額外的引數化版本汙染了你的計畫快取!當你執行下列語句會變得更糟:--execute a slightly different query
2select
*from
orders
3where price =
8.704go
56--execute a slightly different query
7select
*from
orders
8where price =
124.50
9go
--這個會再次給你新的用numeric(6,2)資料型別的新引數化版本——計畫快取裡另乙個版本!當我展示這個行為的時候,很多人都建議我應該用逆序來執行剛才的sql語句。我們通過首先清空計畫快取來試下。execute a slightly different query
select
*from
orders
where price =
1204.50
go
1然後當你看計畫快取時,沒有任何改變:sql server還生成了3個不同的引數化sql語句——每次都用最小可能的資料型別。--clear the plan cache
2dbcc
freeproccache3go
45--execute a slightly different query
6select
*from
orders
7where price =
1204.508go
910--execute a slightly different query
11select
*from
orders
12where price =
124.50
13go
1415
--execute a slightly different query
16select
*from
orders
17where price =
8.70
18go
你怎麼做沒有一點關係,即你執行你sql語句的順序:在自動引數化期間,sql server總會選擇最小可能的資料型別。當你依賴sql server這個特性時,好好考慮下。
varchar如何呢?sql server自動引數化包含字元值(例如varchar)的sql語句時,事情會好點。假設有下列表定義和下列2個查詢:
1在這個情況下,sql server用varchar(8000)生成1個自動引數化sql語句——最大可能的資料型別。從剛才例子裡,這是你所期待的行為。有時sql server好事壞事同時做……--create another table to demonstrate this problem
2create
table
orders33(
4 col1 int
identity(1, 1) primary
keynot
null
,5 col2 varchar(100)6
)7go8
9--clears the plan cache
10dbcc
freeproccache
11go
1213
--a varchar/char column is always auto parametrized to a varchar(8000)
14select
*from
orders3
15where col2 =
'woody'16
go17
18--
a varchar column is always auto parametrized to a varchar(8000)
19select
*from
orders3
20where col2 ='tu
'21go
當你和簡單sql語句打交道時,自動引數化可以非常棒。但如你在這個文章裡所見,你要知道sql server引入的***。另外sql server的簡單引數化特性還會提供你強制引數化(forced parameterization)功能,這個我會在以後的文章裡介紹。
感謝關注!
SQL Server裡簡單引數化的痛苦
在今天的文章裡,我想談下對於即席sql語句 ad hoc sql statements sql server使用的簡單引數化 parameterization 的一些特性和 首先,如果你的sql語句包含這些,簡單引數化不會發生 一般來說,如果你處理所謂的安全執行計畫 safe execution p...
Sql Server 的引數化查詢
為什麼要使用引數化查詢呢?引數化查詢寫起來看起來都麻煩,還不如用拼接sql語句來的方便快捷。當然,拼接sql語句執行查詢雖然看起來方便簡潔,其實不然。遠沒有引數化查詢來的安全和快捷。今天剛好了解了一下關於sql server 引數化查詢和拼接sql語句來執行查詢的一點區別。引數化查詢與拼接sql語句...
簡單介紹SQL Server裡的閂鎖
在今天的文章裡我想談下sql server使用的更高階的,輕量級的同步物件 閂鎖 latch 閂鎖是sql server儲存引擎使用輕量級同步物件,用來保護多執行緒訪問記憶體內結構。文章的第1部分我會介紹sql server裡為什麼需要閂鎖,在第2部分我會給你介紹各個閂鎖型別,還有你如何能對它們進行...