曲演雜壇--HASH的一點理解


HASH,百度百科上做如下定義:

Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的輸入(又叫做預映射, pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小於輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。

 

如此生硬的定義很難理解,我們來點看的見的,CHECKSUM就是一種典型的HASH操作

--==========================================================
SELECT CHECKSUM('SLDKSLKFJDSLKJFDSLAKJF;DSAKLFJDSJASLKF S')
--值為244224724

SELECT CHECKSUM('中啥打算換阿盛大連水庫將盛大阿克蘇打算快樂撒旦')
--值為1349490807

--==============================================================
SELECT CHECKSUM(REPLICATE(CAST('中啥打算換阿盛大連水庫將盛大阿克蘇打算快樂撒旦' AS nvarchar(MAX)),100000)) AS HashKey
,DATALENGTH(REPLICATE(CAST('中啥打算換阿盛大連水庫將盛大阿克蘇打算快樂撒旦' AS nvarchar(MAX)),100000)) AS DataLength
--HashKey=438180382
--DataLength=4600000

 

使用CHECKSUM函數,我們可以很容易根據一個任意長度的字符串得到一個整數值,而且CHECKSUM屬於確定性函數,無論何時執行,相同的字符串,總是能獲得同樣的整數值,CHECKSUM所得值不相同的兩個字符串一定不相同。由此,我們可以在比較兩個長字符串是否相等時,先比較CHECKSUM的值,如果CHECKSUM值不相等則判定兩個字符串不相等,如果CHECKSUM值相等則遍歷每個字符是否相等。

上述操作看起來似乎比直接比較字符串更麻煩,但是不同字符串的CHECKSUM值相等的情況並不多,因此需要遍歷每個字符判斷相等的概率會比較低。

 

除了散列值存儲空間更小和更容易比較外,HASH散列值還有另外一個優點:固定長度和類型,如CHECKSUM返回的就是4字節的INT類型,由於類型和存儲空間相同,我們可以對散列值做進一步操作,將散列值平均分拆到不同的存儲空間上,這樣邊有了HASH桶的概念,如我們可以將CHECKSUM返回的值做取余操作,為每個余數划分一片區域。

--====================================
--准備測試數據
SELECT name INTO HB001
FROM sys.all_objects

--===================================
--查看測試數據
SELECT name AS SourceValue,
CHECKSUM(name) AS HashKey,
ABS(CHECKSUM(name)%1000) AS HashBucket ,FROM HB001 ORDER BY HashBucket

當我們有上面數據后,如果要查詢表中是否有“sp_procedure_params_rowset”,我們便可以先對“sp_procedure_params_rowset”求HashKeyH和HashBucket,先根據HashBucket找到我們要去那片區域查找數據,在根據HashKey和值去匹配這片區域的數據,因此我們需要到HashBucket=2的區域下找,而HashBucket=2的區域下有3條數據,我們只需要比較這三條數據就可以了,避免了對表中數據進行遍歷或排序查找。

 

--=================紅果果的分割線=================--

對HASH有了朦朧了解后,讓我們來看下HASH JOIN步驟:

1. 生成輸入,在生產輸入階段,查詢優化器選擇一個表(或結果集,一般會選擇數據量較小的對象)作為生成輸入,先掃描或計算整個生成輸入,然后在內存中生成哈希表。根據計算得出的哈希鍵的哈希值,將每行插入哈希存儲桶。

2. 探測輸入,當生成輸入結束后,將另外一個表(結果集)作為探測輸入,一次一行地對整個探測輸入進行掃描或計算,並為每個探測行計算哈希鍵的值,掃描相應的哈希存儲桶並生成匹配項。

--=================紅果果的分割線=================--

除了HASH JOIN會使用到HASH外,在分組統計時,也會應用到HASH。

延用上面的數據,當我們需要依據SourceValue來分組求COUNT時,可以先將SourceValue采用HASH分拆到多個HASH桶中,由於相同的SourceValue會被分配到一個HASH桶中,因此我們在做分組統計時,只需要考慮同一個桶中是否有相同的值,而無需考慮其他HASH桶,這樣就避免了我們對整個結果集排序分組的過程。

--=================紅果果的分割線=================--

在做HASH相關操作時,HASH桶的數量和數據均勻分布至關重要,如果HASH桶的數量過少的話,那么每次掃描桶中數據的成本就會上升,如果HASH桶數量過多的話,過多的空桶就會造成資源浪費,數據分布不均勻的話,就會導致某些桶數據過多,某些桶數據過小,對性能也影響也很嚴重。請參照SQL SERVER 2014的內存表的HASH索引

學習HASH,你便不得不看下HASH WARNING

--=================紅果果的分割線=================--

影響聯接的一些因素

1. 聯接兩端的表(結果集)大小

2. 聯接字段上是否排序和排序的開銷

3. 聯接類型是等值聯接還是不等值聯接

4. 服務器可用內存情況

--=================紅果果的分割線=================--

換個口味,上頭GP的冤家,顫栗吧,GP!

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM