在今天的文章裡我想談下sql server裡與索引相關的特殊效能問題。
假設下列的簡單查詢,在你的日常sql server裡,這樣的查詢你已經看到過幾百遍了:
1用那個簡單查詢,我們請求在特定年份特定月份裡的銷售資訊。並不複雜。遺憾的是這個查詢效能很差——即使在orderdate列使用了非聚集索引。當你檢視執行計畫時,你會看到查詢優化器選擇了在orderdate列上的非聚集索引,但遺憾的是sql server進行的索引的全掃瞄,而不是高效的查詢操作。--results in an index scan
2select
*from
sales.salesorderheader
3where
year(orderdate) =
2005
andmonth(orderdate) =74
go
這真不是sql server的侷限性,而是關聯式資料庫的工作和思考方式:)只要你在索引列上使用了表示式(函式呼叫,計算)(即所謂的篩選引數(search argument)),資料庫引擎必須去掃瞄那個索引,而不是進行查詢操作。
在執行計畫裡為了獲得可擴充套件的查詢操作,你必須要換種方式重寫你的查詢來避免datepart函式的呼叫:
1從重寫的查詢可以看到,查詢返回同樣的結果,但我們已經剔除了datepart函式的呼叫。當你檢視執行計畫時,你會看到sql server進行了查詢操作——在那個情況下,這個是所謂的區域性範圍掃瞄(partial range scan):sql server查詢到第1個值,然後掃瞄到請求範圍的最有值。如果你想在索引列上下文呼叫函式,你必須保證在查詢裡,這些函式呼叫的執行在你列的右側。我們來看乙個具體的例子。下面查詢把creditcardid索引列轉化為char(4)資料型別:--results in an index seek
2select
*from
sales.salesorderheader
3where orderdate >=
'20050701
'and orderdate <
'20050801'4
go
1當你仔細看執行計畫時,你會看到sql server再次掃瞄整個非聚集索引。如果你的表越來越大,這是真不能擴充套件的。如果你在查詢裡在你索引列的右側執行轉化,你就可以在索引列上剔除函式呼叫,sql server就可以進行查詢操作:--results in an index scan
2select
*from
sales.salesorderheader
3where
cast(creditcardid as
char(4)) =
'1347'4
go
1從這篇文章裡,你可以看到,在你的索引列裡不直接呼叫任何函式或間接呼叫函式是非常重要的。不然的話sql server會掃瞄你的索引,而不是進行高效的查詢操作。而且當你表越來越大時,掃瞄從不擴充套件。--results in an index seek
2select
*from
sales.salesorderheader
3where creditcardid =
cast('
1347'as
int)
4go
感謝關注。
使用正確的篩選引數來提高查詢效能
假設下列的簡單查詢,在你的日常sql server裡,這樣的查詢你已經看到過幾百遍了 1 results in an index scan 2select from sales.salesorderheader 3where year orderdate 2005 andmonth orderdat...
優化Linux的核心引數來提高伺服器併發處理能力
ps 在伺服器硬體資源額定有限的情況下,最大的壓榨伺服器的效能,提高伺服器的併發處理能力,是很多運維技術人員思考的問題。要提高linux系統下的負載能力,可以使用nginx等原生併發處理能力就很強的web伺服器,如果使用apache的可以啟用其worker模式,來提高其併發處理能力。除此之外,在考慮...
優化Linux的核心引數來提高伺服器併發處理能力
ps 在伺服器硬體資源額定有限的情況下,最大的壓榨伺服器的效能,提高伺服器的併發處理能力,是很多運維技術人員思考的問題。要提高linux 系統下的負載能力,可以使用nginx 等原生併發處理能力就很強的web伺服器,如果使用apache 的可以啟用其worker 模式,來提高其併發處理能力。除此之外...