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!

曲演杂坛--HASH的一点理解的更多相关文章

  1. 曲演杂坛--一条DELETE引发的思考

    原文:曲演杂坛--一条DELETE引发的思考 场景介绍: 我们有一张表,专门用来生成自增ID供业务使用,表结构如下: CREATE TABLE TB001 ( ID ,) PRIMARY KEY, D ...

  2. 曲演杂坛--当ROW_NUMBER遇到TOP

    值班期间研发同事打来电话,说应用有超时,上服务器上检查发现有SQL大批量地执行,该SQL消耗IO资源较多,导致服务器存在IO瓶颈,细看SQL,发现自己都被整蒙了,不知道这SQL是要干啥,处理完问题赶紧 ...

  3. 曲演杂坛--使用TRY CATCH应该注意的一个小细节

    群里一个朋友遇到一个TRY CATCH的小问题,测试后发现是自己从来没有考虑的情况,写篇blog加深下印象 --============================================ ...

  4. 曲演杂坛--重建索引后,还使用混合分区么?(Are mixed pages removed by an index rebuild?)

    原文来自:http://www.sqlskills.com/blogs/paul/mixed-pages-removed-index-rebuild/ 在SQL SERVER 中,区是管理空间的基本单 ...

  5. 曲演杂坛--蛋疼的ROW_NUMBER函数

    使用ROW_NUMBER来分页几乎是家喻户晓的东东了,而且这东西简单易用,简直就是程序员居家必备之杀器,然而ROW_NUMBER也不是一招吃遍天下鲜的无敌BUG般存在,最近就遇到几个小问题,拿出来供大 ...

  6. 曲演杂坛--特殊字符/生僻字与varchar

    对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...

  7. 曲演杂坛--使用CTE时踩的小坑:No Join Predicate

    在一次系统优化中,意外发现一个比较“坑”的SQL,拿出来供大家分享. 生成演示数据: --====================================== --检查测试表是否存在 IF(O ...

  8. 曲演杂坛--为什么SELECT语句会被其他SELECT阻塞?

    很多刚入门的DBA在捕获阻塞得时候,会问这么一个问题“为什么这个SELECT语句被那个SELECT语句阻塞了,难道不是共享锁么?” 让我们来做个小测试,首先准备一些测试数据: --========== ...

  9. 曲演杂坛--EXISTS语句

    通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧! 首先准备测 ...

随机推荐

  1. git的一些常用操作命令

    这些操作命令都是从廖雪峰老师的官网上看过后记下来的,以下是廖雪峰老师的官网,大家可以看看,教程不错~ http://www.liaoxuefeng.com/wiki/00137395163059296 ...

  2. [leetcode]199. Binary Tree Right Side View二叉树右侧视角

    Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...

  3. thinkphp下多语言

    这里指定2种语言 ,zh-cn 和 zh-tw 1.在配置文件中写入 'LANG_SWITCH_ON' => true, // 开启语言包功能 'LANG_AUTO_DETECT' => ...

  4. sobel 使用说明

    转自http://www.cnblogs.com/justany/archive/2012/11/23/2782660.html OpenCV 2.4+ C++ 边缘梯度计算 2012-11-23 0 ...

  5. memcache缓存失效

    缓存过期 memcached在处理过期的缓存项时,采用懒惰模式处理方法. 缓存项过期,不会立即删除,直到对该缓存项执行了get操作,才会删除过期缓存. > set key 0 10 > t ...

  6. oracle JDeveloper学习

    1>oracle JDeveloper官方地址,官方的学习资源包括视频和教材,很全面,很多不知道从和入手. 2>oracle JDeveloper 12C 教程,一步步学习jdev,可以此 ...

  7. 【原创】Silverlight之TextBox的LostFocus、GotFocus事件

    <TextBox x:Name="txtCount" Width="200" Height="35" GotFocus="t ...

  8. IPEndPoint

    .NET框架用IPEndPoint 对象来表示一个特定的IP地址和端口的组合,应用该对象的场景多是在讲socket绑定到本地地址或者将socket绑定到非本地地址.

  9. Vue2.0 keep-alive 组件的最佳实践

    1.基本用法 vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗 <keep-alive> <component> <!-- ...

  10. 冒泡排序java语言实现

    class bubbleSort { public static void main(String[] args){ int[] a={49,38,65,97,76,13,27,49,78,34,12 ...