SQL Server 内存优化表的索引设计
测试的版本:SQL Server 2017
内存优化表上可以创建哈希索引(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);
二,内存优化索引的性能优化
内存优化索引适用的场景是:
- 非聚集索引 如果查询中包含order by子句、或者包含 where index_column > value等范围扫描操作 ,推荐使用非聚集索引。
- 哈希索引 如果查询中包含点查找(point lookup),例如 where index_column = value,而不是范围扫描,推荐使用哈希索引。

1,哈希索引性能优化
哈希索引是指SQL Server引擎应用哈希函数F(x),把索引键值(Index Key)转换为哈希表(哈希索引)。当哈希值相同,而索引键不同时,称作产生一个哈希冲突。把哈希值相同的索引键链接在一起,组成一个链式结构(chain),也称作冲突链。在查找时,需要遍历冲突链来查找数据,因此,冲突链变长,会降低哈希查找的性能。

哈希冲突是不可避免的,以下两种情况,会产生较多的哈希冲突:
- 如果索引键存在大量的重复值,
- 当hashbucket的数量较少时
这两种情况导致哈希冲突链变长,降低哈希查找的性能,用户可以通过降低索引键的重复值、增加hashbucket的数量来减少哈希冲突。
哈希索引只能点查找(point lookup),并且要求在where子句中应用index key的所有字段、等值条件和与逻辑,例如,哈希索引键是colA和colB,在where子句中必须满足:同时出现所有索引键、等值条件和与逻辑,也就是:where colA= value1 and colB=value2,只有这样,才能使用哈希索引进行点查找,否则无法应用哈希索引。
2,内存优化非聚集索引的优化
内存优化非聚集索引的结构是Bw-Tree,在结构上类似于B-Tree结构,具有树形结构、键值是有序的等特点。
从性能上来看,Bw-Tree索引有三个主要特点:
- 通过无锁(Lock-Free)的方式来操作Bw-Tree树,提升了随机读和范围读的性能。
- 索引按照前序字段进行排序,在查找时,索引键的前序字段非常重要,前序字段必须出现在where/on 子句的条件断言中。
- 适合范围查找,只适用于按照索引定义的排序方向的查找,而不能用于逆向排序的查找
- 通过Log-Structed Storage方式写数据,传统的checkpoint写数据的方式是随机写,而Log-Structed Storage是顺序写,提高写操作的性能。
- 对数据的更新采用Delta Update方式,提高了缓存的命中率。
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),为了实现该目的,引入了新的更新机制:
- 在更新页时,不需要latch 和lock
- 索引页不是固定的大小
Bw-Tree结构解决了B-tree高性能读和写不能兼得的问题,可能会存在性能抖动。
四,哈希索引的结构特点
哈希索引包含一个由指针构成的数组,数组中的每个元组叫做一个hash bucket:
- 每个hash bucket占用8Bytes,用于指向key entry构成的链式列表
- 每个entry主要由索引键的值、对应的数据行的地址和指向下一个entry的指针构成
- 每个entry有一个指针,用于指向链中下一个entry,通过这种方式,entry构成链式结构
哈希索引的结构,如下图所示,左侧是哈希表,右侧上一是表数据(Name、City)+时间戳+索引指针,右侧中下的两行是表数据,中间通过Index prt链接为一个chain。

hash bucket的数量必须在索引定义时指定:
- 哈希索引的hash bucket的最大数量是 1,073,741,824
- 较短的链式列表比较长的链式列表性能更好
- hash bucket的数量与表中唯一值的数量的比值越低,每个hash bucket指向的链式列表的长度越长,性能越差。因此,应该适当增加hash bucket的数量。
- 理想情况下,hash bucket最好是表中唯一值数量的1到2倍。
参考文档:
SQL Server 内存优化表的索引设计的更多相关文章
- 使用SQL Server内存优化表 In-Memory OLTP
如果你的系统有高并发的要求,可以尝试使用SQL Server内存优化表来提升你的系统性能.你甚至可以把它当作Redis来使用. 要使用内存优化表,首先要在现在数据库中添加一个支持内存优化的文件组. M ...
- SQL Server 性能优化之——重复索引
原文 http://www.cnblogs.com/BoyceYang/archive/2013/06/16/3139006.html 阅读导航 1. 概述 2. 什么是重复索引 3. 查找重复索引 ...
- Sql server2014 内存优化表 本地编译存储过程
参考文献:http://www.infoq.com/cn/news/2013/09/Compiled-Queries http://www.bianceng.cn/database/SQLServer ...
- 利用DBCC PAGE查看SQL Server中的表和索引数据
16:08 2013-01-06 参考http://doc.chinaunix.net/sqlserver/200810/206034.shtmlDBCC PAGE|IND 参数 DBCC PAGE ...
- SQL Server数据库所有表重建索引
USE My_Database;DECLARE @name varchar(100) DECLARE authors_cursor CURSOR FOR Select [name] from s ...
- 试试SQLSERVER2014的内存优化表
试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...
- SQL Server 内存中OLTP内部机制概述(四)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...
- SQLServer2014内存优化表评测
SQLServer2014内存优化表评测 分类: SQL内存表2014-06-20 11:49 1619人阅读 评论(11) 收藏 举报 目录(?)[-] SQLServer2014的使用基本要求 内 ...
- SQLSERVER2014的内存优化表
SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技术来支持大规模OLTP工作负载. 就算如此, ...
随机推荐
- python基础知识补充
set 集合 {} 无序 集合天然去重 增 : s.add s.update 迭代添加 删 : s.pop( ) 随机删除 返回删除值 s.clear( ) 清空 获取到的是 set( ) del s ...
- 1.Sentinel源码分析—FlowRuleManager加载规则做了什么?
最近我很好奇在RPC中限流熔断降级要怎么做,hystrix已经1年多没有更新了,感觉要被遗弃的感觉,那么我就把眼光聚焦到了阿里的Sentinel,顺便学习一下阿里的源代码. 这一章我主要讲的是Flow ...
- 手把手教你用深度学习做物体检测(六):YOLOv2介绍
本文接着上一篇<手把手教你用深度学习做物体检测(五):YOLOv1介绍>文章,介绍YOLOv2在v1上的改进.有些性能度量指标术语看不懂没关系,后续会有通俗易懂的关于性能度量指标的介绍文章 ...
- https免费证书申请certbot,nginx
官网:https://certbot.eff.org/ 下载: wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto ./certbo ...
- “玲珑杯”ACM比赛 Round #11 B -- 萌萌哒的第二题
DESCRIPTION 一条东西走向的河两边有都排着工厂,北边有n间工厂A提供原材料,南边有n间工厂B进行生产.现在需要在工厂A和工厂B之间建运输桥以减少运输成本.可是每个工厂B只能接受最多6个工厂A ...
- 快速构建第一个Flink工程
本文简述通过maven和gradle快速构建的Flink工程.建议安装好Flink以后构建自己的Flink项目,安装与示例运行请查看:Flink快速入门--安装与示例运行. 在安装好Flink以后,只 ...
- 深入理解SQL Server数据库Select查询原理(一)
使用SQL Server十年有余,但是一直对其Select查询机制原理一致不明,直到最近有个通讯录表,很简单的一张表(但因简单,所以当时并没有考虑按部门排序问题),结果想查询某个单位所有部门(不重复) ...
- Python作业本——第4章 列表
课后习题: 1.[]是一个空列表 2. spam.insert(3, 'hello') 错,应为:spam[2] = 'hello' 3.['d'] 'd' 4.['d'] 'd' 5.[ ...
- Vulkan(1)用apispec生成Vulkan库
Vulkan(1)用apispec生成Vulkan库 我的Vulkan.net库已在(https://github.com/bitzhuwei/Vulkan.net)开源,欢迎交流. apispec. ...
- 代码整洁 vs 代码肮脏
写出整洁的代码,是每个程序员的追求.<clean code>指出,要想写出好的代码,首先得知道什么是肮脏代码.什么是整洁代码:然后通过大量的刻意练习,才能真正写出整洁的代码. WTF/mi ...