SQL Server 2016支持哈希查找,用户可以在内存优化表(Memory-Optimized Table)上创建哈希索引(Hash Index),使用Hash 查找算法,实现数据的极速查找。在使用上,Hash Index 和B-Tree索引的区别是:Hash Index 是无序查找,Index Key必须全部作为查找的条件,多个键值之间是逻辑与关系,并且只能执行等值查找,而B-Tree索引是有序查找,不需要Index Key都作为查找,只需要前序字段都存在,还可以进行大于、小于、等于等比较操作;在存储结构上,Hash Index使用Hash Table实现,存在Hash 冲突,而B-Tree索引的结构是B-Tree结构,存在页拆分和索引碎片等问题。

一,Hash 查找算法

在《数据结构》课程中,Hash查找的算法是:以关键字k为自变量,通过一个映射函数h,计算出对应的函数值y=h(k)(y称作哈希值,或哈希地址),根据函数值y,将关键字k存储在数组(bucket数组)所指向的链表中。在进行哈希查找时,根据关键字,使用相同的函数h计算哈希地址h(k),然后直接寻址相应的Hash bucket,直接到对应的链表中取出数据。因此,Hash 查找算法的数据结构由Hash Bucket数组,映射函数f和数据链表组成,通常将Bucket数组和数据链表称作Hash Table,如图,Hash Table由5个buckets和7个数据结点组成:

哈希查找的时间复杂度是O(n/m),n是指数据结点的数量,m是bucket的数量,在理想情况下,Hash Bucket足够多,Hash函数不产生重复的Hash Value,哈希查找的时间复杂度最优到达O(1),但是,在实际应用中,哈希函数有一定的几率出现重复的哈希地址,产生哈希冲突,时间复杂度会低于O(n/m);在最差的情况下,时间复杂度是O(n)。

二,Hash Index的结构

Hash Index使用Hash查找算法实现,SQL Server内置Hash函数,用于所有的Hash Index,因此,Hash Index就是Hash Table,由Hash Buckets数组和数据行链表组成。创建Hash Index时,通过Hash函数计算Index Key的Hash地址,Hash地址不同的数据行指向不同的Bucket,Hash地址相同的数据行指向相同的Bucket,如果多个数据行的Hash地址相同,都指向同一个Bucket,那么将这些数据行链接在一起,组成一个链表。

A hash index consists of an array of pointers, and each element of the array is called a hash bucket. The index key column in each row has a hash function applied to it, and the result of the function determines which bucket is used for that row. All key values that hash to the same value (have the same result from the hash function) are accessed from the same pointer in the hash index and are linked together in a chain. When a row is added to the table, the hash function is applied to the index key value in the row. If there is duplication of key values, the duplicates will always generate the same function result and thus will always be in the same chain.

举例说明,假定哈希函数是h(k)=Length(k),用于计算Index Key的字符个数,在内存优化表(Name,City)上创建Hash Index,Index ptr指向链表中的下一个数据行,如果没有下一个数据行,那么该指针为NULL:

1,以Name为Index Key创建Hash Index

第一个数据行的Name是“Jane”,HashValue是4,将该行数据映射到下标为4的Bucket中(Bucket数组的第五个元素),由于该数据行是第一个数据结点,Index ptr为NULL。

第二个数据行,Name值是“Greg”,HashValue是4,映射到下标为4的Bucket中,和第一个数据行链接在一起,组成一个链表(Chain),插入数据结点时,使用头部插入法,新的数据节点作为头结点,将头节点的Index ptr(next pointer)指针指向数据链表的第一个数据结点,如图,新的头结点“Greg”的Index ptr指向第一个数据行“Jane”。

2,创建第二个Hash Index,以City为Index Key

当创建第二个Hash Index时,每个数据行结构中包含两个Index ptr指针,都用于指向下一个数据节点(Next Pointer):第一个Index ptr用于Index Key为Name的Hash Index,当出现相同的Hash Value时,该指针指向链表中下一个数据行,使数据行链接到一起组成链表;第二个Index ptr用于Index Key为City的Hash Index,指向链表中下一个数据行。

因此,当创建一个新的Hash Index时,在数据结构上,SQL Server需要创建Hash Buckets数组,并在每个数据行中增加一个Index ptr字段,根据Index Key为Index ptr赋值,组成一个新数据行链表,但是数据行的数量保持不变。

3,Hash 函数

在创建Hash Index时,不需要编写Hash 函数,SQL Server内置Hash函数:

  • 内置的Hash函数产生的HashValue是随机和不可预测的,适用于所有的Hash Index;
  • 内置的Hash函数是确定性的,相同的Index Key总是映射到相同的Bucket;
  • 有一定的几率,多个Index Key会映射到相同的bucket中;
  • 哈希函数是均衡的,产生的Hash Value服从泊松分布;

泊松分布不是均匀分布,Index Key不是均匀地分布在Hash bucket数组中。例如,有n个Hash Bucket,n个不同的Index Key,泊松分布产生的结果是:大约有1/3的Hash Bucket是空的,大约1/3的Hash bucket存储一个Index Key,剩下1/3的Hash Buckets存储2个Index Key。

4,Hash Index的链表长度

不同的Index Key,经过hash函数映射之后,可能生成相同的Hash Value,映射到相同的bucket中,产生 Hash 冲突。Hash算法,将映射到相同Bucket的多个Index Key组成一个链表,链表越长,Hash Index查找性能越差。

在DMV:sys.dm_db_xtp_hash_index_stats (Transact-SQL)中,表示Hash Index链长的字段有:avg_chain_length 和 max_chain_length ,链长应保持在2左右;链长过大,表明太多的数据行被映射到相同的Bucket中,这会显著影响Hash Index的查询性能,导致链长过大的原因是:

  • 总的Bucket数量少,导致不同的Index Key映射到相同的Bucket上;
  • 如果空的Bucket数量大,但链长过大,这说明,Hash Index存在大量重复的Index Key;相同的Index Key被映射到相同的bucket;

三,创建Hash Index

在内存优化表上创建Index,不能使用Create Index命令,SQL Server 2016支持两种方式创建索引:

1,在创建内存优化表时创建Hash Index

创建Hash Index的语法是:

INDEX index_name [ NONCLUSTERED ] HASH WITH (BUCKET_COUNT = bucket_count)  

创建Hash Index的示例:

--create memory optimized table
create table [dbo].[products]
(
[ProductID] [bigint] not null,
[Name] [varchar](64) not null,
[Price] decimal(10,2) not null,
[Unit] varchar(16) not null,
[Description] [varchar](max) null,
constraint [PK__Products_ProductID] primary key nonclustered hash ([ProductID])with (bucket_count=2000000)
,index idx_Products_Price nonclustered([Price] desc)
,index idx_Products_Unit nonclustered hash(Unit) with(bucket_count=40000)
)
with(memory_optimized=on,durability= schema_and_data)
go

2,使用Alter Table命令创建Hash Index

alter table [dbo].[products]
add index hash_idx_Products_Name nonclustered hash(name)with(bucket_count=40000);

四,Hash Index的特点

总结Hash Index的特点:

  • Hash Index使用Hash Table组织Index 结构,每一个数据节点都包含一个指针,指向数据行的内存地址;
  • Hash Index是无序的,适合做单个数据行的Index Seek;
  • 只有当Hash Index Key全部出现在Filter中,SQL Server才会使用Hash Index Seek操作查找相应的数据行,如果缺失任意一个Index Column,那么SQL Server都会执行Full Table Scan以获取符合条件的数据行。例如,创建Hash Index时指定N个column,那么SQL Server对这N个column计算Hash  Value,映射到相应的bucket上,所以,只有当这N个Column都存在时,才能定位到对应的bucket,进而查找相应的数据结点;
Hash indexes require values for all index key columns in order to compute the hash value, and locate the corresponding rows in the hash table. Therefore, if a query includes equality predicates for only a subset of the index keys in the WHERE clause, SQL Server cannot use an index seek to locate the rows corresponding to the predicates in the WHERE clause.

参考文档:

Hash Indexes

Guidelines for Using Indexes on Memory-Optimized Tables

Troubleshooting Common Performance Problems with Memory-Optimized Hash Indexes

Linux内核中的hash与bucket

In-Memory:哈希索引的更多相关文章

  1. MySQL B+树索引和哈希索引的区别

      导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BT ...

  2. B+树索引和哈希索引的区别[转]

    导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...

  3. [日常] MySQL的哈希索引和原理研究测试

    1.哈希索引 :(hash index)基于哈希表实现,只有精确匹配到索引列的查询,才会起到效果.对于每一行数据,存储引擎都会对所有的索引列计算出一个哈希码(hash code),哈希码是一个较小的整 ...

  4. MySQL B+树索引和哈希索引的区别(转 JD二面)

    导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...

  5. mysql索引之一:索引基础(B-Tree索引、哈希索引、聚簇索引、全文(Full-text)索引区别)(唯一索引、最左前缀索引、前缀索引、多列索引)

    没有索引时mysql是如何查询到数据的 索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储10 ...

  6. MySQL技巧--伪哈希索引

    哈希索引 哈希索引就是通过一个哈希函数计算出某个key的hash值,并以这个hash值去找到目标数据.例如:对于数据库的一行数据,对其主键进行hash运算,得到一个地址,这个地址指向这行记录的存储地址 ...

  7. SQL Server2014 哈希索引原理

    SQL Server2014 哈希索引原理 翻译自:http://www.sqlservercentral.com/blogs/sql-and-sql-only/2015/09/08/hekaton- ...

  8. B+树索引和哈希索引的区别——我在想全文搜索引擎为啥不用hash索引而非得使用B+呢?

    哈希文件也称为散列文件,是利用哈希存储方式组织的文件,亦称为直接存取文件.它类似于哈希表,即根据文件中关键字的特点,设计一个哈希函数和处理冲突的方法,将记录哈希到存储设备上. 在哈希文件中,是使用一个 ...

  9. memory引擎的索引失效一例

    memory引擎的索引失效一例 memory引擎的索引失效一例

随机推荐

  1. 更改用户host留下的坑

    前言:  我们在创建数据库用户的时候都会指定host,即一个完整的用户可描述为 'username'@'host' .创建用户时不显式指定host则默认为%,%代表所有ip段都可以使用这个用户,我们也 ...

  2. 使用gunicorn部署python web

    gunicorn 是一款支持wsgi的web服务器, 支持gevent 首先安装setuptools.  wget https://bootstrap.pypa.io/ez_setup.py $pyt ...

  3. windows设置多个JDK环境

    1.查看jdk版本 java -version 2.查看JAVA_HOME和PATH的变量值 echo %JAVA_HOME% set path 3.临时修改环境变量JAVA_HOME和PATH的变量 ...

  4. Java的自动拆装箱与Integer的缓存机制

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10832303.html 一:基本类型与包装类型     我们知道,Java有8大基本数据类型,4整2浮1符1 ...

  5. 目标检测论文解读11——Mask R-CNN

    目的 让Faster R-CNN能做实例分割的任务. 方法 模型的结构图如下. 与Faster R-CNN相比,主要有两点变化. (1) 用RoI Align替代RoI Pool. 首先回顾一下RoI ...

  6. 【AICC】2019训练营笔记

    1.AI 人工的方法在机器上实现智能:机器学习.计算机视觉.规划决策.自然语言处理.认知推理.高效搜索 2.三大学派 符号主义 连接主义:CNN 行为主义 3.两条路线 结构模仿 功能模仿 4.AI芯 ...

  7. conda管理python环境

    https://blog.csdn.net/wld914674505/article/details/80615761 source activate python36

  8. 从Oop-Klass模型看透反射

    <红楼梦>第十二回,贾瑞因痴迷王熙凤,被王熙凤折腾的眼看就快不行了.当然这里面是没有多少爱的,完全因王熙凤的美貌而起.就在这时来了一个跛足道人,带来了一面宝镜,说能治好贾瑞的病.当然这可不 ...

  9. 8-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(Apache 配置SSL,HTTPS连接)

    https://www.cnblogs.com/yangfengwu/p/10947423.html 和当时配置MQTT差不多,去下载证书文件   https://www.cnblogs.com/ya ...

  10. [RN] React Native 使用 react-native-camera 过程中报错 Found react-native-camera 'mlkit' but wasn't required.`

    详细报错如下: Could not resolve all task dependencies for configuration ':app:debugRuntimeClasspath'. Coul ...