SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP)

SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP

概述

内存中OLTP(项目“Hekaton”)是一个全新的、完全集成到SQL Server的数据库引擎组件。 对OLTP工作负载访问中在内存中的数据进行了优化。内存中OLTP能够帮助OLTP工作负载实现显著的性能改善,并减少处理时间。表能被视为“内存优化”,提升内存中的OLTP功能。内存优化表是完全可事务的、并可以使用Transact-SQL进行访问。Transact-SQL存储过程可以编译成为机器码,从而进一步地提高内存优化表的性能。该引擎是专为高并发而设计的,并且阻塞是最小的。

术语

基于磁盘的表:

传统的表存储方式,具有以下主要属性:

· 映射到一个文件组,并且该文件组包含一个或多个文件。

· 每个文件划分为 8 个页区,每页的大小为 8K 字节。

· 可跨多个表共享一个区,但分配的页和表或索引之间存在一对一映射。 换言之,一个页面不能有来自两个或更多表或索引的行。

· 根据需要将数据移到内存(缓冲池)中,并且修改后的或新建的页面将以异步方式写入到主要生成随机 IO 的磁盘。

内存优化表:

内存优化表的存储具有以下主要属性:

· 所有内存优化表都映射到内存优化的文件组。 使用文件流文件组生成此文件组。

· 不存在任何页面,并且数据以行的形式保留。

· 对内存优化表进行的所有更改都通过追加到活动文件进行存储。 对文件进行的读取和写入操作是有顺序的。

· 按照先删除再插入的方式实现更新。 不会立即从存储中移除已删除的行。 依据内存优化表的持久性中所述的策略,已删除的行由称作 MERGE 的后台进程移除。

· 与基于磁盘的表不同,不对内存优化表的存储进行压缩。 在将压缩的(ROW 或 PAGE)基于磁盘的表迁移到内存优化表时,您将需要考虑大小的更改。

· 内存优化表可以是持久的或非持久的。 您只需为持久性内存优化表配置存储。

跨容器的事务:

是指同时参考内存优化表和基于磁盘的表的事务。

互操作性:

是指引用内存优化表的解释型的Transact-SQL。

可编译的Transact-SQL:

即传统的解释性Transact-SQL。当使用互操作时,内存优化表将会访问所有的Transact- SQL区域,但您不应该指望取得使用本地编译存储过程相同的性能。当运行即席查询时,互操作是合适的选择,或在应用程序迁移到内存中的OLTP之前使用。这种使用是最佳性能的关键程序迁移过程中的一个步骤。当您需要同时访问内存优化表和基于磁盘的表时,也可以使用可编译的Transact-SQL 。

Transact-SQL使用互操作访问内存优化表时,不支持的功能仅有以下几种:

· TRUNCATE TABLE;

· MERGE(内存优化表的目标);

· 动态和基于键值集的游标(这些都是自动降级到静态游标);

· 跨数据库中的查询;

· 跨数据库中的事务;

· 链接服务器;

· 锁定提示:TABLOCK、XLOCK、PAGLOCK等(NOLOCK支持);

· 隔离级别的提示READUNCOMMITTED、READCOMMITTED READCOMMITTEDLOCK;

· 内存优化的表类型和表中不只是由CTP1支持的变量。

本地编译的存储过程:

是指一种对象类型,这种类型被内存驻留OLTP所支持;内存驻留OLTP被编译为机器代码,并有可能进一步提高性能,甚至比只使用内存优化表更加优化。另一种替代方案是采用基于解释型的Transact-SQL存储过程,这是SQL Server中常用的、采用基础的编译的存储过程只能引用内存优化表。

包含内存中OLTP组件的SQL Server引擎

虽然内存驻留OLTP 与SQL Server关系型引擎集成,并能通过相同的接口访问,但是其内部的行为和性能却大相径庭。

无论调用本地编译的存储过程或者Transact-SQL,客户端应用程序采用与内存优化表或基于磁盘的表同样的方式连接到TDS处理器。您可以看到解释型的Transact-SQL能通过互操作能力访问内存优化表,但本地编译的存储过程只能访问内存优化表。

使用内存中OLTP

内存中OLTP引擎从2013年6月CTP版本开始,已经成为SQL Server 2014的一部分。内存中OLTP SQL Server的安装是SQL Server安装程序的一部分。内存中OLTP组件只能被安装在一个SQL Server 2014 64位版本中,而不与32位版本兼容。

准备:创建示例数据库

CREATE DATABASE imoltp
GO

第一步:设置数据库支持内存中OLTP

包含内存优化表的任何数据库至少需要有一个MEMORY_OPTIMIZED_DATA文件组。这些文件组用于存储数据和增量文件,这些文件被SQL Server用来恢复内存优化表。虽然创建MEMORY_OPTIMIZED_DATA文件组与创建常规FILESTREAM文件组的语法几乎是相同的,但是还是必须要指定CONTAINS MEMORY_OPTIMIZED_DATA这一选项。

下面通过两种方式来添加MEMORY_OPTIMIZED_DATA文件组和存放FILESTREAM文件的容器。

使用T-SQL实现:

ALTER DATABASE imoltp ADD FILEGROUP imoltp_mod CONTAINS MEMORY_OPTIMIZED_DATA
ALTER DATABASE imoltp ADD FILE (name=‘imoltp_mod1‘, filename=‘E:\SQL-DATA\imoltp_mod1‘) TO FILEGROUP imoltp_mod
GO

使用SSMS实现:

1. 在Object Explorer中, 展开数据库节点, 右键点击数据库,单击属性。  

2. 添加一个新的内存优化数据的文件组,点击文件组页面。在MEMORY OPTIMIZED DATA选项下,单击添加文件组并设置文件组的各项值。  

3. 在文件组中添加文件,点击general 页面。 在Database files下,点击添加并且输入文件的各项值。File type 设置为FILESTREAM Data。  

第二步:创建内存优化表

创建优化内存表的语法与创建基于磁盘的表的语法几乎相同,只有一些限制以及需要的扩展。指定表是内存优化表是用MEMORY_OPTIMIZED= ON语句实现的。内存优化表只可以有以下这些可支持的数据类型的列:

· 字节;

· 所有整数类型:tinyint、smallint、int、bigint;

· 所有money类型:money、smallmoney;

· 所有浮点类型:float、real;

· 所有日期/时间类型:datetime、smalldatetime、datetime2、date、time;

· 数字和浮点数类型;

· 所有非LOB字符类型:char(n)、varchar(n)、nchar(n)、nvarchar(n)、sysname;

· 非LOB二进制类型:binary(n)、varbinary(n);

· 独特的识别符。

请注意的是LOB数据类型是不可用的;不能有XML类型、CLR、或者max数据类型的列,并且所有行的长度都限制在8060个字节之内,而且没有行外数据。事实上,8060字节的限制是在表创建的时候执行的,所以不像基于磁盘的表,内存优化表不能创建两个varchar(5000)的列。

内存优化表可以通过两种DURABILITY值定义:SCHEMA_AND_DATA或SCHEMA_ONLY,前者是默认值。内存优化表由DURABILITY=SCHEMA_ONLY定义,这意味着表中数据的变化没有被记录下来,并且表中的数据并没有保存在磁盘上。但是,架构会被作为数据库元数据的一部分保存下来,所以在一个SQL Server重启的过程中恢复数据库之后,这样的空表是可用的。

如前所述,内存优化表必须至少有一个索引,但这一要求能通过索引自动创建来满足,从而支持主键约束。除了那些用schema_only选项所创建的表以外的其他表都必须有一个声明的主键。至少有一个索引必须声明支持一个主键约束。下面的示例显示了一个主键索引创建成为一个分区索引,其中的统计指标也必须被指定。

当创建内存优化表时,除已列的对数据类型的限制之外,只有少数的其他限制:

· 没有DML触发器;

· 没有FOREIGN KEY或CHECK约束;

· 没有IDENTITY列;

· 除了主键没有唯一索引;

· 最多8个索引,包括支持主键的索引。

此外,一旦一个表被创建后,架构是不可改变的。您将需要删除并重新创建表,而不是使用ALTER TABLE。此外,并没有具体的索引DDL命令(比如创建索引、修改索引、删除索引)。索引总是作为表创建的一部分而创建。

目前我们有两张表,‘ShoppingCart’和‘UserSession’。‘ShoppingCart’是一个持久化的表(默认值),这意味着表中的内容是存储在磁盘上的,不会因为服务器崩溃而丢失。‘UserSession’是一个非持久化的表(DURABILITY=SCHEMA_ONLY),这意味着表中内容仅存储在内存中,服务器重启即会丢失。

注:SQL 2014 内存优化的表支持非聚集哈希索引(hash index)和非聚集索引(rang index)。hash索引的Bucket_cout建议值是表中能找到的唯一索引键值个数的4到8倍。

下面通过两种方式来创建内存优化表。

使用T-SQL实现:

USE imoltp
GO
-- durable table (持久化的表)
CREATE TABLE dbo.ShoppingCart (
ShoppingCartId int not null primary key nonclustered hash with
(bucket_count=2000000),
UserId int not null index ix_UserId nonclustered hash with (bucket_count=1000000),
CreatedDate datetime2 not null,
TotalPrice money
)
WITH (MEMORY_OPTIMIZED=ON)
GO
-- non-durable table (非持久化的表)
CREATE TABLE dbo.UserSession (
SessionId int not null primary key nonclustered hash with (bucket_count=400000),
UserId int not null,
CreatedDate datetime2 not null,
ShoppingCartId int,
index ix_UserId nonclustered hash (UserId) with (bucket_count=400000)
)
WITH(MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_ONLY)
GO

使用SSMS实现:

1. 在Object Explorer,右键单击您数据库的Tables节点,点击new,然后点击Memory Optimized Table。然后可以看到创建内存优化表的模板。  

2. 替换模板中的参数,在query菜单中点击Specify Values for Template Parameters。快捷键是Ctrl-Shift-M。  

3. 执行完毕后,确认表已创建。  

第三步:加载数据

可以通过多种方式把数据加载到表中,包括 INSERT .. SELECT from一个已经存在的存储在磁盘上的表和BCP。

-- insert a few rows
INSERT dbo.UserSession VALUES (1,342,GETUTCDATE(),4)
INSERT dbo.UserSession VALUES (2,65,GETUTCDATE(),NULL)
INSERT dbo.UserSession VALUES (3,8798,GETUTCDATE(),1)
INSERT dbo.UserSession VALUES (4,80,GETUTCDATE(),NULL)
INSERT dbo.UserSession VALUES (5,4321,GETUTCDATE(),NULL)
INSERT dbo.UserSession VALUES (6,8578,GETUTCDATE(),NULL)
INSERT dbo.ShoppingCart VALUES (1,8798,GETUTCDATE(),NULL)
INSERT dbo.ShoppingCart VALUES (2,23,GETUTCDATE(),45.4)
INSERT dbo.ShoppingCart VALUES (3,80,GETUTCDATE(),NULL)
INSERT dbo.ShoppingCart VALUES (4,342,GETUTCDATE(),65.4)
GO
-- verify table contents
SELECT * FROM dbo.UserSession
SELECT * FROM dbo.ShoppingCart
GO

第四步:更新统计信息

内存优化的表不支持auto_update_statistics,因此统计信息需要手动进行更新。您可以使用UPDATE STATISTICS来更新单个表的统计信息或者sp_updatestats来更新数据库中的所有表的统计信息。

-- update statistics on memory optimized tables
UPDATE STATISTICS dbo.UserSession WITH FULLSCAN, NORECOMPUTE
UPDATE STATISTICS dbo.ShoppingCart WITH FULLSCAN, NORECOMPUTE
GO

第五步:执行查询

优化内存表可以以两种不同的方式访问:要么通过可编译的Transact-SQL互操作,或通过本地编译的存储过程。

现在您已经做好了执行查询的准备。因为查询需要访问内存优化的表,他们将会受益于不加锁的数据结构,从而提高了数据访问的效率。以下是一些例子:

-- in an explicit transaction, assign a cart to a session and update the total price.
-- note that the isolation level hint is required for memory-optimized tables with
-- SELECT/UPDATE/DELETEstatements in explicit transactions
BEGIN TRAN
UPDATE dbo.UserSession WITH (SNAPSHOT) SET ShoppingCartId=3 WHERE SessionId=4
UPDATE dbo.ShoppingCart WITH (SNAPSHOT) SET TotalPrice=65.84 WHERE ShoppingCartId=3
COMMIT
GO
-- verify table contents
SELECT * FROM dbo.UserSession u JOIN dbo.ShoppingCart s on u.ShoppingCartId=s.ShoppingCartId
WHERE u.SessionId=4
GO

第六步:创建本地编译的存储过程

为了进一步优化内存优化表的访问以及优化您的业务逻辑的执行,您可以选择创建本地编译的存储过程。这些存储过程是使用Transact-SQL创建的,但并不支持完整的Transaction-SQL环境。具体细节可参考联机丛书。

以下是一个访问之前我们创建的表的本地编译的存储过程的例子。

-- natively compiled stored procedure for assigning a shopping cart to a session
CREATE PROCEDURE dbo.usp_AssignCart @SessionId int
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N‘us_english‘)
DECLARE @UserId int,
@ShoppingCartId int
SELECT @UserId=UserId, @ShoppingCartId=ShoppingCartId
FROM dbo.UserSession WHERE [email protected]
IF @UserId IS NULL
THROW 51000, ‘The session or shopping cart does not exist.‘, 1
UPDATE dbo.UserSession SET [email protected] WHERE [email protected]
END
GO
EXEC usp_AssignCart 1
GO

下面的存储过程通过向内存优化表中插入大量数据行来测试本地编译的存储过程的性能。该脚本插入了1,000,000行数据。

需要注意的是如果写事物日志文件变成应用的性能瓶颈,SQL Server允许您采用非持久化的表(DURABILITY=SCHEMA_ONLY)来完全除去写事务日志。

-- natively compiled stored procedure for inserting a large number of rows
-- this demonstrates the performance of native procs
CREATE PROCEDURE dbo.usp_InsertSampleCarts @StartId int, @InsertCount int
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N‘us_english‘)
DECLARE @ShoppingCartId int = @StartId
WHILE @ShoppingCartId < @StartId + @InsertCount
BEGIN
INSERT INTO dbo.ShoppingCart VALUES
(@ShoppingCartId, 1, ‘2013-01-01T00:00:00‘, NULL)
SET @ShoppingCartId += 1
END
END
GO
-- insert 1,000,000 rows
DECLARE @StartId int = (SELECT MAX(ShoppingCartId)+1 FROM dbo.ShoppingCart)
EXEC usp_InsertSampleCarts @StartId, 1000000
GO
-- verify the rows have been inserted
SELECT COUNT(*) FROM dbo.ShoppingCart
GO

使用SSMS创建本地编译的存储过程:

1. 在 Object Explorer中,右键单击您的数据库中的Stored Procedures 节点,点击New,然后点击 Natively Compiled Stored Procedure。创建本地编译的存储过程的模板将会显示在界面上。  

2. 替换模板中的参数,点击Query 菜单下的 Specify Values for Template Parameters。快捷键是Ctrl-Shift-M。  

SQL Server功能支持

很多SQL Server功能所支持的内存驻留OLTP和数据库包含内存优化表。例如,AlwaysOn的组件,日志传送和数据库备份和恢复被完全支持。但是,数据库镜像和复制不被支持。您可以使用SQL Server Management Studio以支持内存优化表和SSIS工作。

对于支持和不支持的功能的完整列表,请参阅到SQL Server 内存驻留OLTP文档。

总结

SQL Server内存驻留OLTP提供了可创造和运行内存优化的极其高效的管理,实现了对OLTP工作负载的性能优化。真正实现了多版本的积极并发控制,且无需在访问过程中锁定。所有内存驻留OLTP内存优化表必须至少拥有一个索引,然后所有对这类表的访问都需要通过这些索引进行。除少量限制情况下外,内存驻留OLTP内存优化表可以作为基于磁盘表中的相同引用的事务。本地编译的存储过程以最快的方式来使用您的内存优化表和性能业务逻辑计算。

时间: 2024-12-25 20:18:23

SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP)的相关文章

SQL Server 2014新功能 -- 缓冲池扩展(Buffer Pool Extension)

支持版本 缓冲池扩展(Buffer Pool Extension)此功能仅可用于64位 SQL Server 2014 Enterprise/Business Intelligence/Standard版本. 术语解释 缓冲区 在 SQL Server 中,一个缓冲区就是一个 8 KB 大小的内存页,其大小与一个数据页或索引页相同. 因此,缓冲区缓存被划分为多个 8KB 页. 缓冲区缓存中会保留一页,直到缓冲区管理器需要该缓冲区读入更多数据. 数据只有在被修改后才重新写入磁盘. 这些内存中已修改

谈谈我的微软特约稿:《SQL Server 2014 新特性:IO资源调控》

原文:谈谈我的微软特约稿:<SQL Server 2014 新特性:IO资源调控> 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 篡写经历(Experience) 特约稿正文(Content-body) 第一部分:生活中资源调控器: 第二部分:SQL Server中资源调控器: 第三部分:SQL Server资源调控器运用场景—CPU: 第四部分:SQL Server资源调控器运用场景—IO: 第五部分:总结: 第六部分:作者简介:

SQL Server 2014新特性——Buffer Pool扩展

Buffer Pool扩展 Buffer Pool扩展是buffer pool 和非易失的SSD硬盘做连接.以SSD硬盘的特点来提高随机读性能. 缓冲池扩展优点 SQL Server读以随机读为主,SQL Server IO分为2部分:buffer pool管理方式,和buffer pool. SQL Server 从磁盘中读入数据,并且存放在buffer pool中以供读取和修改,修改完之后脏数据还是放在buffer pool中,当内存紧张执行lazy write把脏数据写入磁盘,并且释放内存

SQL Server 2014新特性:其他

AlwaysOn 增强功能 SQL Server 2014 包含针对 AlwaysOn 故障转移群集实例和 AlwaysOn 可用性组的以下增强功能: “添加 Azure 副本向导”简化了用于 AlwaysOn 可用性组的混合解决方案创建.有关详细信息,请参阅使用“添加 Azure 副本向导”(SQL Server). 辅助副本的最大数目从 4 增加到 8. 断开与主副本的连接时,或者在缺少群集仲裁期间,可读辅助副本现在保持可用于读取工作负荷. 故障转移群集实例 (FCI) 现在可使用群集共享卷

insert into values 插入多条指定记录 - sql server 2008新功能

之前碰到一条如下语句 declare @t1 table (catId int, id int) insert into @t1(catid,id) values (15,33), (15,49), (15,113) sql server 2000及2005上跑,均报错--Line 3: Incorrect syntax near ','. 后来查了一下,这是sql server2008出来的新特性.所以此语句仅限于sql server 2008及以上版本使用. PS:顺道提一下,sql ser

【Transact-SQL】SQL Server 2012新功能之一:转换函数

在SQL Server 2012中,新增了几个转换函数,用于支持数据类型的强制转化. 由于之前主要用的是SQL Server 2008R2,而公司的项目为了提高开发效率,很多表的列都为varchar类型,但也会存储数字. 当对这些列进行聚合计算,比如sum时,要先进行cast转换为numeric类型,经常会报错,现在有了这些新的函数,可以先try一下,通过判断返回值是否为null,我们可以判断字段值是否为数字,如果不是数字,就直接过滤到,所以这些函数非常实用,希望对大家有用. 1.PARSE函数

Sql Server 2016 新功能——内置的 Temporal Tables

放假之前老大跟我提起了一下2016有个有趣的功能叫 Temporal Table ,今天去看了一下资料整理一下. 这个功能看上去像是临时表,但是其实是系统维护的一个历史记录表.(在某个程度上面比起我们手动维护的历史表应该方便了一点的) 简单直接的说,它的界面看起来是这样的(就像是T1一样) 创建了之后,就会在下面有一个T1History的表中表来记录. 然后我们来试下怎么去玩这个功能.首先,确认你的Sql Server 版本是2016.然后我们通过一个这样的语句来创建表 Use Test go

第16/24周 SQL Server 2014中的基数计算

大家好,欢迎回到性能调优培训.上个星期我们讨论在SQL Server里基数计算过程里的一些问题.今天我们继续详细谈下,SQL Server 2014里引入的新基数计算. 新基数计算 SQL Server 2014里一个增强是新的基数计算.上个星期你已经学到老基数计算有些限制,会生成错误的估计,这会导致不好的执行计划表现.截至SQL Server 2012,你一直在使用自SQL Server 7.0引入的基数计算. 当然,几年来也有很多问题被修正,但默认它们都没启用的——你需要启用SQL Serv

SQL Server 2014 SP1 通过补丁KB3058865提供更新,SP1一文便知

Microsoft SQL Server 2014 SP1 更新: SQLServer2014SP1-KB3058865-architecture-language.exe 安装完成后版本 12.0.4100.1. 主要特性包如下: Microsoft® SQL Server® Backup to Windows® Azure® Tool Microsoft SQL Server Backup to Windows Azure Tool 支持备份到 Windows Azure Blob 存储,加