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

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

概述


内存中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关系型引擎集成,并能通过相同的接口访问,但是其内部的行为和性能却大相径庭。

image

 

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

 

使用内存中OLTP


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

 

准备:创建示例数据库

1
2
CREATE  DATABASE  imoltp
GO

 

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

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

 

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

 

使用T-SQL实现:

1
2
3
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中, 展开数据库节点, 右键点击数据库,单击属性。   
image

 

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

 

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

 

第二步:创建内存优化表

创建优化内存表的语法与创建基于磁盘的表的语法几乎相同,只有一些限制以及需要的扩展。指定表是内存优化表是用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实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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。然后可以看到创建内存优化表的模板。   
image

 

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

 

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

 

第三步:加载数据

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 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来更新数据库中的所有表的统计信息。

 

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

 

第五步:执行查询

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

 

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

 

1
2
3
4
5
6
7
8
9
10
11
12
-- 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

 

image

 

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

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

 

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 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  SessionId=@SessionId
IF @UserId  IS  NULL
THROW 51000,  'The session or shopping cart does not exist.' , 1
UPDATE  dbo.UserSession  SET  ShoppingCartId=@ShoppingCartId  WHERE  SessionId=@SessionId
END
GO
EXEC  usp_AssignCart 1
GO

 

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

 

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 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。创建本地编译的存储过程的模板将会显示在界面上。   
image

 

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

 

SQL Server功能支持


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

 

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

 

总结

 

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


















本文转自UltraSQL51CTO博客,原文链接: http://blog.51cto.com/ultrasql/1626514,如需转载请自行联系原作者



相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
12天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
51 10
|
1月前
|
SQL 数据库 数据安全/隐私保护
Sql Server数据库Sa密码如何修改
Sql Server数据库Sa密码如何修改
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之数据查询
【数据库SQL server】关系数据库标准语言SQL之数据查询
96 0
|
2月前
|
SQL 算法 数据库
【数据库SQL server】关系数据库标准语言SQL之视图
【数据库SQL server】关系数据库标准语言SQL之视图
77 0
|
22天前
|
SQL
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
启动mysq异常The server quit without updating PID file [FAILED]sql/data/***.pi根本解决方案
16 0
|
12天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
74 6
|
7天前
|
SQL 安全 网络安全
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
IDEA DataGrip连接sqlserver 提示驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接的解决方法
15 0
|
12天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
16天前
|
SQL 数据安全/隐私保护
SQL Server 2016安装教程
SQL Server 2016安装教程
17 1
|
16天前
|
SQL 安全 Java
SQL server 2017安装教程
SQL server 2017安装教程
15 1

热门文章

最新文章