SQL Server 内存优化表的索引设计

Posted ljhdo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server 内存优化表的索引设计相关的知识,希望对你有一定的参考价值。

测试的版本:SQL Server 2017

内存优化表上可以创建三种类型的索引,分别是:Hash Index、内存优化非聚集(NONCLUSTERED)索引和聚集(CLUSTERED)列存储索引。

本文着重分享非聚集索引和哈希索引,这两个索引适用的场景是:

  • 非聚集索引   如果查询中包含order by子句、或者包含 where index_column > value等范围扫描操作 ,推荐使用非聚集索引。
  • 哈希索引       如果查询中包含点查找(point lookup),例如 where index_column = value,而不是范围扫描,推荐使用哈希索引。

一,创建内存优化表的索引

在创建内存优化表的索引时,第一种方式是在创建表时定义索引,第二种方式是先创建内存优化表,然后通过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);  

二,内存非聚集索引的内在结构

内存非聚集索引类似于B-Tree结构,称作Bw-Tree,是一个新型的B-Tree结构。从高层次上来看,Bw-Tree可以理解为按照Page ID组织的页面映射。

在Bw-Tree结构中,每个索引Page具有一组有序键值(该结构类似于普通的B树),键值是按照大小顺序排列的,并且索引中包含层次结构,父级别指向子级别,叶级别指向数据行。

差异是Bw-Tree可以把多个数据行连接在一起,级别中的页面指针是逻辑页面的ID,这个逻辑页面的ID实际上是页面映射表的偏移量,该映射表具有每个页面的物理地址,通过偏移量找到每个页面在内存中实际的物理地址。

在内存非聚集索引中,没有索引页的就地更新(in place update),为了实现该目的,引入了新的更新机制:

  • 在更新页时,不需要latch 和lock
  • 索引页不是固定的大小

在非叶子级别中,父级别的页面中存储的键值是它指向的子级页面中的键值的最大值,并且每一行还包含该页面逻辑页ID(偏移量)。叶级数据页不仅包含键值,还包含页面的物理地址。

三,哈希索引的内部结构

哈希索引包含一个由指针构成的数组,数组中的每个元组叫做一个hash bucket:

  • 每个hash bucket占用8Bytes,用于指向key entry构成的链式列表
  • 每个entry主要由索引键的值、对应的数据行的地址和指向下一个entry的指针构成
  • 每个entry有一个指针,用于指向链中下一个entry,通过这种方式,entry构成链式结构

hash bucket的数量必须在索引定义时指定:

  • 哈希索引的hash bucket的最大数量是 1,073,741,824
  • 较短的链式列表比较长的链式列表性能更好
  • hash bucket的数量与表中唯一值的数量的比值越低,每个hash bucket指向的链式列表的长度越长,性能越差。因此,应该适当增加hash bucket的数量。
  • 理想情况下,hash bucket最好是表中唯一值数量的1到2倍。

 

参考文档:

Index Architecture & Design

以上是关于SQL Server 内存优化表的索引设计的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2016新特性:列存储索引新特性

SQL Server 2016:内存列存储索引

SQL Server 数据库性能优化

SQL Server查询优化方法

50种方法优化SQL Server数据库查询

50种方法优化SQL Server数据库查询