SQL Server 並行操做優化,避免並行操做被抑制而影響SQL的執行效率

 

爲何我也要說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,不但要有過硬的技術,也要有足夠的耐心,才能看清事物的本質。
  對並行的理解還不夠充分,有不對的地方但願各位看官指出,謝謝。

 

出處:http://www.cnblogs.com/wy123/p/5661848.html

相關文章
相關標籤/搜索