测试的版本:SQL Server 2017sql
内存优化表上能够建立哈希索引(Hash Index)和内存优化非汇集(NONCLUSTERED)索引,这两种类型的索引也是内存优化的,称做内存优化索引,和基于硬盘的传统索引有很大的区别:数组
在建立内存优化表的索引时,第一种方式是在建立表时定义索引,第二种方式是先建立内存优化表,而后经过alter table命令修改表结构,向表中添加索引,而表级别的索引语法以下所示:缓存
<table_index> ::= INDEX index_name { [ NONCLUSTERED ] HASH (column [ ,... n ] ) WITH (BUCKET_COUNT = bucket_count) | [ NONCLUSTERED ] (column [ ASC | DESC ] [ ,... n ] ) [ ON filegroup_name | default ] }
举个例子,修改表结构,向表中添加哈希索引,在定义索引时必须设置bucket_count的数量:性能优化
ALTER TABLE table_name ADD INDEX idx_hash_index_name HASH (index_key) WITH (BUCKET_COUNT = 64);
内存优化索引适用的场景是:app
1,哈希索引性能优化ide
哈希索引是指SQL Server引擎应用哈希函数F(x),把索引键值(Index Key)转换为哈希表(哈希索引)。当哈希值相同,而索引键不一样时,称做产生一个哈希冲突。把哈希值相同的索引键连接在一块儿,组成一个链式结构(chain),也称做冲突链。在查找时,须要遍历冲突链来查找数据,所以,冲突链变长,会下降哈希查找的性能。函数
哈希冲突是不可避免的,如下两种状况,会产生较多的哈希冲突:性能
这两种状况致使哈希冲突链变长,下降哈希查找的性能,用户能够经过下降索引键的重复值、增长hashbucket的数量来减小哈希冲突。测试
哈希索引只能点查找(point lookup),而且要求在where子句中应用index key的全部字段、等值条件和与逻辑,例如,哈希索引键是colA和colB,在where子句中必须知足:同时出现全部索引键、等值条件和与逻辑,也就是:where colA= value1 and colB=value2,只有这样,才能使用哈希索引进行点查找,不然没法应用哈希索引。优化
2,内存优化非汇集索引的优化
内存优化非汇集索引的结构是Bw-Tree,在结构上相似于B-Tree结构,具备树形结构、键值是有序的等特色。
从性能上来看,Bw-Tree索引有三个主要特色:
Bw-Tree结构的索引,和普通的B-Tree结构相比,读写性能提升,解决了高性能读和写不能兼得的问题。
内存非汇集索引相似于B-Tree结构,称做Bw-Tree。从总体上看,Bw-Tree是按照Page ID组织的页面映射。
在Bw-Tree结构中,每一个索引Page具备一组有序键值(该结构相似于普通的B树),键值是按照大小顺序排列的,而且索引中包含层次结构,父级别指向子级别,叶级别指向数据行。
差别是Bw-Tree能够把多个数据行链接在一块儿,索引结构中的页面指针是逻辑页面的ID,这个逻辑页面的ID其实是页面映射表的偏移量,该映射表具备每一个页面的物理地址,经过偏移量找到每一个页面在内存中实际的物理地址。
在非叶子级别中,父级别的页面中存储的键值是它指向的子级页面中的键值的最大值,而且每一行还包含该页面逻辑页ID(偏移量)。叶级数据页不只包含键值,还包含页面的物理地址。
Bw-Tree结构大体以下图所示:有相似B-Tree的树形结构(存储的数据和索引)和Mapping Table(存储逻辑页面ID和物理地址的映射)。
在内存非汇集索引中,没有索引页的就地更新(in-place update),为了实现该目的,引入了新的更新机制:
Bw-Tree结构解决了B-tree高性能读和写不能兼得的问题,可能会存在性能抖动。
哈希索引包含一个由指针构成的数组,数组中的每一个元组叫作一个hash bucket:
哈希索引的结构,以下图所示,左侧是哈希表,右侧上一是表数据(Name、City)+时间戳+索引指针,右侧中下的两行是表数据,中间经过Index prt连接为一个chain。
hash bucket的数量必须在索引定义时指定:
参考文档: