Sql server聚合函數(shù)在實際工作中應(yīng)對各種需求使用的還是很廣泛的,對于聚合函數(shù)的優(yōu)化自然也就成為了一個重點,一個程序優(yōu)化的好不好直接決定了這個程序的聲明周期。Sql server聚合函數(shù)對一組值執(zhí)行計算并返回單一的值。聚合函數(shù)對一組值執(zhí)行計算,并返回單個值。除了 COUNT 以外,聚合函數(shù)都會忽略空值。 聚合函數(shù)經(jīng)常與 SELECT 語句的 GROUP BY 子句一起使用。
一.寫在前面
如果有對Sql server聚合函數(shù)不熟或者忘記了的可以看我之前的一片博客。
本文中所有數(shù)據(jù)演示都是用Microsoft官方示例數(shù)據(jù)庫:Northwind,至于Northwind大家也可以在網(wǎng)上下載。
二.Sql server標(biāo)量聚合
2.1.概念:在只包含聚合函數(shù)的 SELECT 語句列列表中指定的一種聚合函數(shù)(如 MIN()、MAX()、COUNT()、SUM() 或 AVG())。當(dāng)列列表只包含聚合函數(shù)時,則結(jié)果集只具有一個行給出聚合值,該值由與 WHERE 子句謂詞相匹配的源行計算得到。
2.2.探索標(biāo)量聚合:
我們先用Sql server的"包括實際的執(zhí)行計劃"來看看一個簡單的流聚合COUNT()來看看表里數(shù)據(jù)所有的行數(shù)。
再通過SET SHOWPLAN_ALL ON(關(guān)于輸出中包含的列更多信息可以在鏈接中查看)來看看有關(guān)語句執(zhí)行情況的詳細信息,并估計語句對資源的需求。
通過SET SHOWPLAN_ALL ON我們來看看COUNT()具體做了那些事情:
- 索引掃描:掃描當(dāng)前表的行數(shù)
- 流計算:計算行數(shù)的數(shù)量
- 計算標(biāo)量:將流計算出來的結(jié)果轉(zhuǎn)化為適當(dāng)?shù)念愋汀?因為索引掃描出來的結(jié)果是根據(jù)表中數(shù)據(jù)的大小決定的,如果表中數(shù)據(jù)很多的話,COUNT是int類型就會有問題,所以在最終返回的時候需要將默認(rèn)類型(數(shù)值一般默認(rèn)類型是Big)轉(zhuǎn)成int類型。)
- 小結(jié):通過SET SHOWPLAN_ALL ON我們可以查看Sql server聚合函數(shù)在給我們呈現(xiàn)最終效果的時候,為這個效果做了些什么事情。
2.3.標(biāo)量聚合優(yōu)化技巧:
我們通過兩個比較簡單的sql查詢來看看他們的區(qū)別
復(fù)制代碼 代碼如下:
SELECT COUNT(DISTINCT ShipCity) FROM OrdersSELECT COUNT(DISTINCT OrderID) FROM Orders
從上圖中可以看到,其實這兩個查詢從語句上來說沒什么太大的區(qū)別,但是為什么開銷會不一樣,一個是查詢城市一個是查詢訂單號。這是因為其實DISTINCT對于OrderID查詢來說,是沒有什么意義的,因為OrderID是主鍵,是不會有重復(fù)的。而ShipCity是會有重復(fù)的,Sql server的去重機制在去重的時候,會有一個排序的過程。這個排序還是比較消耗資源的。
對于數(shù)據(jù)量比較大的表其實不是很建議對大表排序或者對大表的某個重復(fù)次數(shù)多的字段去重運算。所以我們這里可以對ShipCity進行優(yōu)化一下??梢詫hipCity創(chuàng)建一個非聚集索引。
復(fù)制代碼 代碼如下:
CREATE INDEX Index_ShipCity On Orders(ShipCity desc)go
從上圖中可以看到,加了索引以后COUNT(DISTINCT ShipCity)的查詢變成了兩個流聚合,而沒有了排序,節(jié)省了開銷。
總結(jié):對于標(biāo)量聚合從上面的例子大家可以看到,標(biāo)量聚合優(yōu)缺點很明顯:
- Sql server標(biāo)量聚合優(yōu)點:算法比較簡單直觀,適合非重復(fù)值的聚合操作。Sql server標(biāo)量聚合缺點:性能較差(需要排序),不適合重復(fù)值的聚合操作。
- 優(yōu)化技巧:盡量避免排序產(chǎn)生,將分組字(GROUP BY)段鎖定在索引覆蓋范圍內(nèi)
三.Sql server哈希聚合
3.1.概念:
哈希(Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的輸入(又叫做預(yù)映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠小于輸入的空間,不同的輸入可能會散列成相同的輸出,所以不可能從散列值來唯一的確定輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。)
哈希聚合的內(nèi)部實現(xiàn)方法和哈希連接的實現(xiàn)機制一樣,需要哈希函數(shù)的內(nèi)部運算,形成不同的哈希值,依次并行掃描數(shù)據(jù)形成聚合值。
3.2.背景:
為了解決流聚合的不足,應(yīng)對大數(shù)據(jù)的操作,所以哈希聚合就誕生了。
3.3.分析:
來看看兩個簡單的查詢。
ShipCountry和CustomerID的分組查詢看上去很類似,但是為什么執(zhí)行計劃會不同呢?這是因為ShipCountry包含了大量的重復(fù)值,CustomerID重復(fù)值非常少,所以Sql server系統(tǒng)給ShipCountry推送的哈希聚合,而CustomerID推送的是流聚合。也就是說Sql server系統(tǒng)會動態(tài)的根據(jù)查詢的情況選擇合適的聚合方式。所以我們在做SQL優(yōu)化的時候不能僅根據(jù)SQL語句來優(yōu)化,還得結(jié)合具體數(shù)據(jù)分布的環(huán)境。
四.運算過程監(jiān)控指標(biāo)
4.1.監(jiān)控元素:
可視化查看運行時間T-sql語句查詢時間占用內(nèi)存T-sql語句查詢IO
4.2.可視化查看運行時間:
4.3.T-sql語句查詢時間:
4.4.占用內(nèi)存:
4.5.T-sql語句查詢IO:
關(guān)于監(jiān)控元素還有很多,這里就列舉幾個。
SQL Server 聚合函數(shù)算法優(yōu)化技巧差不多就介紹到這里,希望對大家優(yōu)化聚合函數(shù)算法有所幫助。
您可能感興趣的文章:- Sql Server 2000 行轉(zhuǎn)列的實現(xiàn)(橫排)
- Sql Server 字符串聚合函數(shù)
- sqlserver2005 行列轉(zhuǎn)換實現(xiàn)方法
- sqlserver 行列互轉(zhuǎn)實現(xiàn)小結(jié)
- sqlserver下將數(shù)據(jù)庫記錄的列記錄轉(zhuǎn)換成行記錄的方法
- SQLServer行轉(zhuǎn)列實現(xiàn)思路記錄
- SQLServer行列互轉(zhuǎn)實現(xiàn)思路(聚合函數(shù))