简介:
内存数据库(In-Memory OLTP),代号Hekaton
如果数据都是在内存中,那么当前的数据库优化器产生的执行计划是没什么意义的,因为现在的优化器默认数据在磁盘中而不是在内存中,所以不从磁盘中读取数据,优化器应该使用新的执行计划和新的开销算法。
In-Memory OLTP 减少了锁等待问题,使用基于行版本来优化同步的控制,改善了写入等待的延迟,写入日志变少,写入次数变少。
专业名词
Memory-optimized tables(索引优化表):引入了新的结构,被加入到in-memory oltp的新表
Disk-Based tables(磁盘表):基础磁盘存放的表,就是我们一直使用的表。
Natively complied(原生编译)存储过程:用于索引优化表的访问,也可以使用tsql访问,通过原生编译存储过程访问速度会更快一点
嵌套事务:可以在优化表中使用,也可以在磁盘表中使用
interop:可以让tsql访问索引优化表
通过图可以发现,原生编译存储过程只能使用在内存优化表上,而query interop用户tsql访问内存优化表的桥梁
创建数据库
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);
内存优化表使用内存字节地址,来代替磁盘区块地址,不想堆表,内存优化表的行并不是存放在一起的,而是通过一个标记,来指明是同一个索引
结构图
每行分为,行头和payload。
行头有begints(行插入时间),endts(行删除时间),stmtid(保存事务中的语句id),idxlinkcount(索引引用计数器,若为0,会被指向到垃圾回收器),最后面8个字节*索引个数,说明内存表的索引。
payload是数据区,包含key和所有其他列,所以hash索引都是覆盖索引。
Hash索引
hash索引是一组指针,每个组中的单元叫做hash bucket,index key通过hash计算把所有相同的hash值用同一个指针。
当索引被创建的时候,必须制定bucket大小,大小必须大于表中会产生的bucket大小,每个bucket都是使用内存的,并且是2的整数次幂,若设置的太多不但不会提升性能,然后会在扫描的时候降低性能。
数据操作
通过维护一个内部事务id(时间戳)来确定一个事务可见的行版本。
有三个时间需要留意:
隔离级别
内存数据库支持一下几种隔离级别:
只有在自动提交事务里面才能支持读提交隔离级别,显式事务或者隐式提交事务都不支持读提交隔离级别
当不访问硬盘表的自动提交事务可以支持读提交快照,当使用TSQL启用快照隔离级别,不能访问内存优化表,当使用TSQL使用串行隔离级别,要使用快照隔离级别访问访问内存优化表。
DML
删除:删除操作只会在endtx上写入一个时间戳,表示数据是否活跃,任何活动中的事务要访问这条数据,在时间戳范围内,都要看是否在该记录还是活跃。
插入/修改:修改操作时先插入后删除,任何写冲突的事务都会直接报错,修改完成后,要开始检查隔离级别,如果隔离级别不对,那么就回滚。任何修改都会被记入write set中,有个指针执行相关的行。
读取:以读取时间为时间点,读取可以覆盖读取时间的行
验证:因为内存数据库没有锁,所以要使用验证来保证一致性:
解释型TSQL
通过interop可以使用tsql访问内存优化表,性能比原生编译存储过程差,但是方便,易兼容。
不支持,truncate,merge,动态、键值游标,交叉数据库查询,交叉数据库事务,连接服务器,锁提示,READUNCOMMITTED,READCOMMITTED,READCOMMITTEDLOCK这几个隔离界别的提示,内存表类型和变量不支持。
原生编译存储过程
优点:可以执行的更快,有不少的限制,如数据类型和排序规则,不能用于访问硬盘表
缺点:兼容性差
SQL Server 2014 新特性——内存数据库(转载)
原文:https://www.cnblogs.com/OpenCoder/p/10147972.html