HASH,百度百科上做如下定义:
Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, PRe-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
如此生硬的定义很难理解,我们来点看的见的,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函数,我们可以很容易根据一个任意长度的字符串得到一个整数值,而且CHECKSUM属于确定性函数,无论何时执行,相同的字符串,总是能获得同样的整数值,CHECKSUM所得值不相同的两个字符串一定不相同。由此,我们可以在比较两个长字符串是否相等时,先比较CHECKSUM的值,如果CHECKSUM值不相等则判定两个字符串不相等,如果CHECKSUM值相等则遍历每个字符是否相等。
上述操作看起来似乎比直接比较字符串更麻烦,但是不同字符串的CHECKSUM值相等的情况并不多,因此需要遍历每个字符判断相等的概率会比较低。
除了散列值存储空间更小和更容易比较外,HASH散列值还有另外一个优点:固定长度和类型,如CHECKSUM返回的就是4字节的INT类型,由于类型和存储空间相同,我们可以对散列值做进一步操作,将散列值平均分拆到不同的存储空间上,这样边有了HASH桶的概念,如我们可以将CHECKSUM返回的值做取余操作,为每个余数划分一片区域。
--====================================--准备测试数据SELECT name INTO HB001FROM sys.all_objects--===================================--查看测试数据SELECT name AS SourceValue,CHECKSUM(name) AS HashKey,ABS(CHECKSUM(name)%1000) AS HashBucket,FROM HB001ORDER 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!
新闻热点
疑难解答