爲何我也要說SQL Server的並行:html
這幾天園子裏寫關於SQL Server並行的文章不少,無論怎麼樣,都讓人對並行操做有了更深入的認識。
我想說的是:儘管並行操做可能(並非必定)存在這樣或者那樣的問題,可是咱們不可否認並行,仍然要利用好並行。
可是,實際開發中,某些SQL語句的寫法會致使用不到並行,從而影響到SQL的執行效率
因此,本文要表達的是:咱們要利用好並行,不要讓一些SQL的寫法問題「抑制」了並行,讓咱們享受不了並行帶來的快感數據庫
關於SQL Server的並行:服務器
所謂的並行,指SQL Server對於那些執行代價相對較大(這個相對跟你的設置有關)的SQL時,若是數據庫服務器存在多顆CPU,
SQL Server查詢引擎會採用並行的方式,也即採用多顆CPU參與整個運算過程,每顆CPU「分擔」一部分計算任務,最後彙總合併各個CPU的計算的一種行爲
有時候,不當的並行查詢不但不會加快查詢的速度,想反會拖慢查詢的效率,若是採用不當的並行操做,甚至會影響到整個服務器的穩定性。
因此SQL Server 究竟在多大代價下啓用並行,是由配置的,這個配置可根據具體的狀況作修改,有人說這個值的單位是「秒」,貌似沒見過權威的資料說過到底單位是什麼,這裏暫不追究
有清楚這個閾值單位的園友情不惜賜教,謝了
函數
儘管並行操做可能存在這樣活着那樣的問題,可是咱們不能因噎廢食,利用好並行,每每老是利大於弊。
可是並非全部的執行代價較大SQL都能用到並行操做,實際開發中,有一些SQL的寫法會抑制到並行操做,結果,致使整個SQL語句(存儲過程)的效率上不去。
下面來舉例說明。
性能
並行查詢是如何變成了串行的:優化
以下是一個很是簡單的查詢操做,這些寫法下,默認狀況下開啓了並行,能夠看到,一共開啓了8個線程來對SQL語句作計算。spa
固然這SQL的執行效率還算不錯,CPU時間是622毫秒,執行總時間是130毫秒,
這裏不要弄混淆了,CPU時間的633毫秒,是8個CPU一共消耗的CPU時間,大於總的執行130毫秒很正常的線程
下面建立一個很是簡單的函數,code
CREATE function [dbo].[fn_justFunction](@p_date date) returns date as begin return @p_date end
這個函數並無什麼實際意義,執行也很是簡單,傳入一個時間,返回這個時間,htm
固然這裏只是爲了下面的操做演示,你徹底能夠說我蛋疼,我只是爲了演示並行被抑制的現象
翻翻你的SQL代碼,有沒有相似這種寫法?
而後咱們這麼寫這個查詢,就是在查詢條件上這麼處理CreateDate>dbo.fn_justFunction('2015-1-1')(注意不是表的列,而是函數做用在查詢條件上),
注意這個函數並不影響任何查詢結果,傳入的2015-1-1,返回位依舊是2015-1-1,可是這麼一變化,並行就變成串行的了,
SQL執行期間只有一個CPU飈了起來,使用了到達80%左右,,與此同時其餘CPU跟沒事人同樣,也不上來幫忙,仍是很閒
還記得上面並行操做方式執行時間是多少麼?130毫秒,如今粗看起來是多少,這裏是4S,也就是4000毫秒
能夠看到,並行操做和串行操做的效率差異仍是很大的,對於CPU的利用也不充分(固然我不是強調必定要用滿全部的CPU纔算合理)
再次強調一點,這裏並非在表的字段上加函數抑制了索引什麼的,純粹的影響到的是並行操做。
固然,抑制並行的寫法不僅僅是在查詢條件在使用函數,實際開發中,影響會更大,
由於實際業務中數據有可能會更大,SQL也可能更加複雜,這種狀況可能更加難以甄別。
好比鏈接條件上,以下,鏈接條件上使用函數致使沒法使用並行的狀況,也是實際開發中遇到的
select * from TableA a inner join TableB b on a.id=b.id and a.Column=dbo.function(@Variable) where ***
固然抑制到並行操做的不僅僅只有這兩種寫法,還有可能潛在其餘相似的寫法也會影響到並行查詢。
這就要求咱們在寫SQL的時候,不但要注意不能再字段上使用函數(沒法使用該字段上的索引),一樣,查詢條件上也儘量不要使用函數,有可能影響到並行操做。
總結起來有一下幾種狀況會抑制到並行的使用(之後發現再更新):
1,將函數之類的操做做用在查詢條件上
好比:CreateDate>dbo.fn_justFunction('2015-1-1')
2,將函數之類的操做做用在鏈接條件上
好比:select * from TableA a inner join TableB b on a.id=b.id and a.Column=dbo.function(@Variable) where ***
3,強函數之類的操做做用在查詢列上
好比:FunctionName(ColumnName)>55,這種狀況,若是查詢列上有索引,不只僅是抑制索引,還會抑制並行
如何處理並行操做被抑制的狀況:
若是要解決相似這些個問題,該怎麼辦?
其實也很簡單,建議查詢條件經過函數運算以後賦值給一個變量,用變量去做爲查詢條件進行查詢。
再次開始了愉快的並行,享受並行帶來的快感。
對於鏈接條件上的函數處理也相似,將結果計算出來以後,保存在一個變量中,把變量寫在鏈接條件中,
固然可能有其餘辦法,我暫時尚未想到。
總結:
本文經過一個簡單的例子演示了並行操做被抑制的現象,說明了並行和串行在執行一個代價較大的SQL上的性能的巨大的差異
其中提到的查詢方式是查詢條件上由於函數的緣由抑制了並行,徹底區別於在查詢列上使用函數抑制索引的狀況。
並行查詢能夠充分調動CPU資源,以高效的方式完成查詢,合理的利用並行會很大程度上提升SQL的執行效率。
爲了利用好並行,在寫SQL的時候,必定要注意,防止並行操做遭到抑制,給性能帶來影響。
SQL優化是一個艱難而又反覆的過程,即使如此,也樂在其中。
面對繁複SQL,不但要有過硬的技術,也要有足夠的耐心,才能看清事物的本質。
對並行的理解還不夠充分,有不對的地方但願各位看官指出,謝謝。