• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PowerCoder
博客园    首页    新随笔    联系   管理    订阅  订阅

SQL Server 2014 新特性——内存数据库(转载)

目录

SQL Server 2014 新特性——内存数据库

简介:

设计目的和原因:

专业名词

In-Memory OLTP不同之处

内存优化表

内存优化表的索引

并发能力的提升

和竞争对手相比几点

Getting Start

内存数据库的使用

存储

TSQL支持

 

简介:
内存数据库(In-Memory OLTP),代号Hekaton

 

设计目的和原因:

  1. 将请求的负荷放到内存中
  2. 减少数据延迟
  3. 来适应特殊的负荷类型

 

如果数据都是在内存中,那么当前的数据库优化器产生的执行计划是没什么意义的,因为现在的优化器默认数据在磁盘中而不是在内存中,所以不从磁盘中读取数据,优化器应该使用新的执行计划和新的开销算法。

 

In-Memory OLTP 减少了锁等待问题,使用基于行版本来优化同步的控制,改善了写入等待的延迟,写入日志变少,写入次数变少。

 

专业名词
Memory-optimized tables(索引优化表):引入了新的结构,被加入到in-memory oltp的新表

Disk-Based tables(磁盘表):基础磁盘存放的表,就是我们一直使用的表。

Natively complied(原生编译)存储过程:用于索引优化表的访问,也可以使用tsql访问,通过原生编译存储过程访问速度会更快一点

嵌套事务:可以在优化表中使用,也可以在磁盘表中使用

interop:可以让tsql访问索引优化表

 

In-Memory OLTP不同之处

通过图可以发现,原生编译存储过程只能使用在内存优化表上,而query interop用户tsql访问内存优化表的桥梁

 

内存优化表

  1. 内存优化表和硬盘表不同,不需要把数据从硬盘上读取放入cache中,
  2. checkpoint只是用户恢复的目的
  3. 和硬盘表一样,使用事务日志,当服务重启后,使用checkpoint的文件和日志,对内存优化表进行重建
  4. 内存优化表可以通过选项来设置表的持久性:SCHEMA_ONLY只保存表的结构,不保存数据,当服务重启后数据就会丢失

 

内存优化表的索引

  1. 内存优化表中的索引不再以btree方式存储,而是以hash 表的方式
  2. 内存优化表必须有一个索引,并没有堆表的概念
  3. 索引,不会被保存在文件或者事务日志,并会根据内存优化表的修改自动维护,在所有重启时,根据表的文件和日志重建索引

 

并发能力的提升

  1. 以行版本的方式存储表数据,修改数据时会请求锁,但是在内存优化表中不会
  2. 虽然没有写入锁,但是还是有等待比如log write,比硬盘表高效,写入的日志少,速度快

 

和竞争对手相比几点

  1. 内存表和硬盘表通过interop集成,有利于过渡
  2. 原生编译存储过程,效率高
  3. hash索引,提高内存访问效率
  4. 没有page,不会出现page latch的等待
  5. 通过行版本实现,不需要lock和latch

 

Getting Start
内存数据库的使用

创建数据库

CREATE DATABASE HKDB

ON

PRIMARY(NAME = [HKDB_data],

FILENAME = 'Q:\data\HKDB_data.mdf', size=500MB),

FILEGROUP [SampleDB_mod_fg] CONTAINS MEMORY_OPTIMIZED_DATA

(NAME = [HKDB_mod_dir],

FILENAME = 'R:\data\HKDB_mod_dir'),

(NAME = [HKDB_mod_dir],

FILENAME = 'S:\data\HKDB_mod_dir')

LOG ON (name = [SampleDB_log], Filename='L:\log\HKDB_log.ldf', size=500MB)

COLLATE Latin1_General_100_BIN2;

在创建库时需要制定 MEMORY_OPTIMIZED_DATA文件组,用来保存checkpoint和delta文件,

创建的数据库只能使用BIN2排序规则,原生编译存储过程只能支持在这些规则上比较,排序,分组

 

添加MEMORY_OPTIMIZED_DATA到已有数据库

ALTER DATABASE AdventureWorks2012 ADD FILEGROUP hk_mod CONTAINS MEMORY_OPTIMIZED_DATA;

GO

ALTER DATABASE AdventureWorks2012 ADD FILE (NAME='hk_mod', FILENAME='c:\data\hk_mod')

TO FILEGROUP hk_mod;

GO

 

创建表

CREATE TABLE T1 (

[Name] varchar(32) not null PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1024),

[City] varchar(32) null,

[LastModified] datetime not null,

) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);

 

  1. 创建内存优化表是需要注明,MEMORY_OPTIMIZED=ON,并设置持久性
  2. BLOB的数据类型是不被支持的
  3. 有2个持久性选项:1.SCHEMA_AND_DATA持久化数据和结构,2.SCHEMA_ONLY只持久化结构
  4. 每个表至少有一个索引,会自动为主键约束创建索引,在创建索引是要指定hash索引的bucket_count
  5. 创建表后,内存数据库引擎会自动加载用于DML的原生编译存储过程,像加载ddl一样
  6. SQL Server 自身不操作内存数据库的数据,而是通过ddl来操作
  7. 内存数据库的限制:1.没有触发器,2.没有外键和check,3.没有identity,4.没有主键以外的唯一索引5.最大8个索引,包括主键索引,9.不能通过alter table修改表结构,索引没有DDL,索引是和表一体的,作为表的一部分创建

 

存储
行

内存优化表使用内存字节地址,来代替磁盘区块地址,不想堆表,内存优化表的行并不是存放在一起的,而是通过一个标记,来指明是同一个索引

结构图

每行分为,行头和payload。

行头有begints(行插入时间),endts(行删除时间),stmtid(保存事务中的语句id),idxlinkcount(索引引用计数器,若为0,会被指向到垃圾回收器),最后面8个字节*索引个数,说明内存表的索引。

payload是数据区,包含key和所有其他列,所以hash索引都是覆盖索引。

 

Hash索引
hash索引是一组指针,每个组中的单元叫做hash bucket,index key通过hash计算把所有相同的hash值用同一个指针。

当索引被创建的时候,必须制定bucket大小,大小必须大于表中会产生的bucket大小,每个bucket都是使用内存的,并且是2的整数次幂,若设置的太多不但不会提升性能,然后会在扫描的时候降低性能。

 

数据操作
通过维护一个内部事务id(时间戳)来确定一个事务可见的行版本。

有三个时间需要留意:

  1. Commit/End Time 每个事务数据被修改的时间都称为 Commit Time或者End Time
  2. Valid Time 可用时间,由3部分组成,BeginTx(行版本插入时间),Endtx(行版本删除时间),在之间的就是可用时间
  3. Logical Read Time 读时间可以是事务开始到现在的任何时间,只要行版本的可用时间可以覆盖读时间,那么行版本就是可读的,对于读提交之外的隔离级别读取时间是事务的开始时间,对于读提交读取时间是语句的执行时间。

 

隔离级别
内存数据库支持一下几种隔离级别:

  1. 快照
  2. 可持续读
  3. 串行

只有在自动提交事务里面才能支持读提交隔离级别,显式事务或者隐式提交事务都不支持读提交隔离级别

当不访问硬盘表的自动提交事务可以支持读提交快照,当使用TSQL启用快照隔离级别,不能访问内存优化表,当使用TSQL使用串行隔离级别,要使用快照隔离级别访问访问内存优化表。

 

DML
删除:删除操作只会在endtx上写入一个时间戳,表示数据是否活跃,任何活动中的事务要访问这条数据,在时间戳范围内,都要看是否在该记录还是活跃。

插入/修改:修改操作时先插入后删除,任何写冲突的事务都会直接报错,修改完成后,要开始检查隔离级别,如果隔离级别不对,那么就回滚。任何修改都会被记入write set中,有个指针执行相关的行。

读取:以读取时间为时间点,读取可以覆盖读取时间的行

验证:因为内存数据库没有锁,所以要使用验证来保证一致性:

  1. 快照隔离级别,commit出错,由2个以上插入同一个主键
  2. 可持续读,读取的行,在提交前被另外一个事务修改
  3. 串行,读取可用行出错,或者出现幻影,无法保证串行

 

TSQL支持

 

解释型TSQL
通过interop可以使用tsql访问内存优化表,性能比原生编译存储过程差,但是方便,易兼容。

不支持,truncate,merge,动态、键值游标,交叉数据库查询,交叉数据库事务,连接服务器,锁提示,READUNCOMMITTED,READCOMMITTED,READCOMMITTEDLOCK这几个隔离界别的提示,内存表类型和变量不支持。

 

原生编译存储过程
优点:可以执行的更快,有不少的限制,如数据类型和排序规则,不能用于访问硬盘表

缺点:兼容性差

 

 

原文链接

 

posted @ 2018-12-20 10:46  PowerCoder  阅读(2371)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3