HASH,百度百科上做如下定義:
Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的輸入(又叫做預(yù)映射, PRe-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
如此生硬的定義很難理解,我們來點(diǎn)看的見的,CHECKSUM就是一種典型的HASH操作
--==========================================================SELECT CHECKSUM('SLDKSLKFJDSLKJFDSLAKJF;DSAKLFJDSJASLKF S')--值為244224724SELECT 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函數(shù),我們可以很容易根據(jù)一個(gè)任意長度的字符串得到一個(gè)整數(shù)值,而且CHECKSUM屬于確定性函數(shù),無論何時(shí)執(zhí)行,相同的字符串,總是能獲得同樣的整數(shù)值,CHECKSUM所得值不相同的兩個(gè)字符串一定不相同。由此,我們可以在比較兩個(gè)長字符串是否相等時(shí),先比較CHECKSUM的值,如果CHECKSUM值不相等則判定兩個(gè)字符串不相等,如果CHECKSUM值相等則遍歷每個(gè)字符是否相等。
上述操作看起來似乎比直接比較字符串更麻煩,但是不同字符串的CHECKSUM值相等的情況并不多,因此需要遍歷每個(gè)字符判斷相等的概率會比較低。
除了散列值存儲空間更小和更容易比較外,HASH散列值還有另外一個(gè)優(yōu)點(diǎn):固定長度和類型,如CHECKSUM返回的就是4字節(jié)的INT類型,由于類型和存儲空間相同,我們可以對散列值做進(jìn)一步操作,將散列值平均分拆到不同的存儲空間上,這樣邊有了HASH桶的概念,如我們可以將CHECKSUM返回的值做取余操作,為每個(gè)余數(shù)劃分一片區(qū)域。
--====================================--準(zhǔn)備測試數(shù)據(jù)SELECT name INTO HB001FROM sys.all_objects--===================================--查看測試數(shù)據(jù)SELECT name AS SourceValue,CHECKSUM(name) AS HashKey,ABS(CHECKSUM(name)%1000) AS HashBucket,FROM HB001ORDER BY HashBucket
當(dāng)我們有上面數(shù)據(jù)后,如果要查詢表中是否有“sp_procedure_params_rowset”,我們便可以先對“sp_procedure_params_rowset”求HashKeyH和HashBucket,先根據(jù)HashBucket找到我們要去那片區(qū)域查找數(shù)據(jù),在根據(jù)HashKey和值去匹配這片區(qū)域的數(shù)據(jù),因此我們需要到HashBucket=2的區(qū)域下找,而HashBucket=2的區(qū)域下有3條數(shù)據(jù),我們只需要比較這三條數(shù)據(jù)就可以了,避免了對表中數(shù)據(jù)進(jìn)行遍歷或排序查找。
--=================紅果果的分割線=================--
對HASH有了朦朧了解后,讓我們來看下HASH JOIN步驟:
1. 生成輸入,在生產(chǎn)輸入階段,查詢優(yōu)化器選擇一個(gè)表(或結(jié)果集,一般會選擇數(shù)據(jù)量較小的對象)作為生成輸入,先掃描或計(jì)算整個(gè)生成輸入,然后在內(nèi)存中生成哈希表。根據(jù)計(jì)算得出的哈希鍵的哈希值,將每行插入哈希存儲桶。
2. 探測輸入,當(dāng)生成輸入結(jié)束后,將另外一個(gè)表(結(jié)果集)作為探測輸入,一次一行地對整個(gè)探測輸入進(jìn)行掃描或計(jì)算,并為每個(gè)探測行計(jì)算哈希鍵的值,掃描相應(yīng)的哈希存儲桶并生成匹配項(xiàng)。
--=================紅果果的分割線=================--
除了HASH JOIN會使用到HASH外,在分組統(tǒng)計(jì)時(shí),也會應(yīng)用到HASH。
延用上面的數(shù)據(jù),當(dāng)我們需要依據(jù)SourceValue來分組求COUNT時(shí),可以先將SourceValue采用HASH分拆到多個(gè)HASH桶中,由于相同的SourceValue會被分配到一個(gè)HASH桶中,因此我們在做分組統(tǒng)計(jì)時(shí),只需要考慮同一個(gè)桶中是否有相同的值,而無需考慮其他HASH桶,這樣就避免了我們對整個(gè)結(jié)果集排序分組的過程。
--=================紅果果的分割線=================--
在做HASH相關(guān)操作時(shí),HASH桶的數(shù)量和數(shù)據(jù)均勻分布至關(guān)重要,如果HASH桶的數(shù)量過少的話,那么每次掃描桶中數(shù)據(jù)的成本就會上升,如果HASH桶數(shù)量過多的話,過多的空桶就會造成資源浪費(fèi),數(shù)據(jù)分布不均勻的話,就會導(dǎo)致某些桶數(shù)據(jù)過多,某些桶數(shù)據(jù)過小,對性能也影響也很嚴(yán)重。請參照SQL SERVER 2014的內(nèi)存表的HASH索引。
學(xué)習(xí)HASH,你便不得不看下HASH WARNING
--=================紅果果的分割線=================--
影響聯(lián)接的一些因素
1. 聯(lián)接兩端的表(結(jié)果集)大小
2. 聯(lián)接字段上是否排序和排序的開銷
3. 聯(lián)接類型是等值聯(lián)接還是不等值聯(lián)接
4. 服務(wù)器可用內(nèi)存情況
--=================紅果果的分割線=================--
換個(gè)口味,上頭GP的冤家,顫栗吧,GP!
|
新聞熱點(diǎn)
疑難解答
圖片精選