SQL Server 2016中In-Memory OLTP继CTP3之后的新改进

Posted 桦仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server 2016中In-Memory OLTP继CTP3之后的新改进相关的知识,希望对你有一定的参考价值。

SQL Server 2016中In-Memory OLTP继CTP3之后的新改进

转译自:https://blogs.msdn.microsoft.com/sqlserverstorageengine/2016/03/25/whats-new-for-in-memory-oltp-in-sql-server-2016-since-ctp3/

SQL Server 2016正在对 In-Memory OLTP 功能作一系列的强化,从而使该功能使用起来更加方便,性能更优。
在之前的文章中,我已经对SQL Server 2016 以及后来的CTP3版本的新增功能进行了汇总说明。
而自那时开始,我们又在原有功能的基础上增加了一些新功能,包括空索引键列、LOB类型字段和自动更新统计信息。
以下是我们为处于CTP3和RC0版本之间的In-Memory OLTP增加的新特性。
在下文的新特性列表中,您将会看到关于LOBs和其它off-row 列、表结构修改和统计信息改进方面的更详细的说明。

CTP3与RC0功能层之间新增的In-Memory OLTP新特性

Transact-SQL 改进:
1、本地模块中查询表面:
2、LOB数据类型 :现在可以使用[varchar(max), nvarchar(max)与varbinary(max)]作为输入参数与变量.
3、OUTPUT 子句:目前在本地编译存储过程中, INSERT,UPDATE 与DELETE也已包含OUTPUT 子句。
4、@@SPID:这一内置功能得到本地编译T-SQL 模块的支持,约束条件见内存优化表。
5、内存优化表支持的功能增加如下:
6、NULLable索引键列。现在允许在内存优化表的索引键中添加NULLable列。
7、Large row: 内存优化表的列可使用LOB数据类型[varchar(max), nvarchar(max与varbinary(max)]。此外,列中无LOB数据类型时,内存优化表的行大小也可超过8060字节。详细说明见下文。
8、内存优化表中的唯一索引。现在索引可指定为UNIQUE。
9、堆扫描: 查询处理程序可在内存中直接扫描堆数据结构表中的各行。需要进行全表扫描时,这种方法比全索引扫描更有效。
10、并行扫描: 所有索引类型及基本堆表现在都支持并行扫描。可以增强分析型查询扫描大型数据集的性能。
11、缩短更新所需停机时间: 从SQL Server 2016的较早版本更新至最新版本不再需要运行数据库恢复。因此,数据大小不再影响升级时间。针对SQL Server 2014升级与附加/还原,数据库需要重启一次,所以SQL2014 数据库升级所需的停机时间约为[数据库恢复所需时间].
12、日志优化与并行ALTER TABLE: 目前,大部分ALTER TABLE都是并行的,并优化写入事务日志。优化指的是只写入元数据变化。有关例外的详细讨论见下文。


统计信息的改进:
1、现在支持自动更新统计信息。不再需要手动更新统计信息。
2、现在支持统计信息采样。可以改进统计信息收集的性能。
请注意,不支持自动重新编译本地模块。需要使用sp_recompile进行手动重新编译。


LOB和其他off-row 列
内存优化表与本地编译T-SQL模块现在已经支持支持大对象(LOB)数据类型varchar(max), nvarchar(max)与varbinary(max),且大小限制跟基于磁盘的表一样(LOB数据类型数据不能超过2GB )。此外,即使表中无LOB数据类型列时,内存优化表的行大小也可超过8060字节。根据表的定义,行的大小或各行数据无运行时间限制。当然,所有数据也需要装入内存。
即使现在支持LOB类型列,但仍推荐列的大小小于8060字节来实现最佳性能。详细信息见下文。
下列T-SQL 脚本可以说明具有多个non-LOB列与单个LOB列的表:

CREATE TABLE dbo.LargeTableSample
(
      Id   int IDENTITY PRIMARY KEY NONCLUSTERED,
      C1   nvarchar(4000),
      C2   nvarchar(4000),
      C3   nvarchar(4000),
      C4   nvarchar(4000),
      Misc nvarchar(max)
) WITH (MEMORY_OPTIMIZED = ON);
GO

 

LOB列和其他列等无法装入in-row的8060字节的存储在off-row,in-row只存储off-row的8字节引用。另外会有一个内部表来单独存储每个off-row列。
将列装入on-row或off-row的逻辑如下所示,每次ALTER TABLE操作都须确保遵循以下规则。
1、如果数据列超过了行大小限制的8060字节,那么最大列将被存储在off-row。例如,在一个表包含varbinary(8000)的列要加入varbinary(2000)列,那么会将原本在in-row的varbinary(8000)列将被移至off-row。
2、所有索引键列都必须存储在in-row;如果索引键列为无法存在在in-row的表,则无法添加索引。考虑之前例子中的那张表。如果在varbinary(8000)列中创建索引,那么varbinary(8000)列被移入in-row,而varbinary(2000)列被移至off-row,因为索引键列必须存储在in-row。
下列查询显示了所有的列都被存储在off-row,依据它们列的大小与内存使用情况。

SELECT object_name(moa.object_id) AD table, c.name AS column, c.max_length
FROM sys.memory_optimized_tables_internal_attributes moa
     JOIN sys.columns c ON moa.object_id = c.object_id AND moa.minor_id=c.column_id
WHERE moa.type=5

 

使用下列查询可以了解到更多有关行off-row的内存消耗,查询显示了所有存储在内部表的off-row列和off-row索引的内存消耗:

SELECT
  OBJECT_NAME(moa.object_id) AS table,
  c.name AS column,
  c.max_length,
  mc.memory_consumer_desc,
  mc.index_id,
  mc.allocated_bytes,
  mc.used_bytes
FROM sys.memory_optimized_tables_internal_attributes moa
   JOIN sys.columns c ON moa.object_id = c.object_id AND moa.minor_id=c.column_id
   JOIN sys.dm_db_xtp_memory_consumers mc ON moa.xtp_object_id=mc.xtp_object_id
WHERE moa.type=5


ALTER TABLE优化
ALTER TABLE一般用于更改架构及调优索引。详细语法与范例见有关 Altering Memory-Optimizes Tables文档。
SQL Server 2016中,内存优化表内的 ALTER TABLE操作是脱机完成的,也就是说操作过程中无法进行表的查询。所有的对内存优化表数据结构的更改和操作 包括列和索引变更都是利用创建新表并复制旧表数据来完成的。在一个10GB 的表中进行ALTER操作在采用24个逻辑处理器的服务器上并行运行,大约需要一分钟就可以完成,这一时间随着表的大小而变化。另一个好消息是现在可以在一个ALTER TABLE 语句中组合多个ADD, DROP或 ALTER操作。 例如,你现在完全可以在一个ALTER TABLE 语句中添加一个列,一条索引,还可以再添加一个约束。
大部分ALTER TABLE场景都是并行运行的,而且都经过事务日志优化,事务日志优化指的是只在事务日志中写入元数据变化。但部分ALTER TABLE操作是单线程的,而且并不能进行日志优化,也就是说将完整的表复制进事务日志中,作为ALTER TABLE事务的一部分。
下面列举的ALTER 操作都是单线程的,而且不能进行日志优化:
1、ADD/ALTER一个使用大对象(LOB)数据类型的列:nvarchar(max), varchar(max)或varbinary(max)。
2、ADD/DROP 一个COLUMNSTORE列存储索引。.
3、ADD/ALTER一个off-row列,那么ADD/ALTER/DROP操作会引起in-row列移至off-row,或off-row列移至in-row。
注意: 使用ALTER语句增加一个off-row列的长度是可以进行日志优化的。

 


统计信息的改进
现在对内存优化表的统计信息已经可以自动更新,并支持统计信息采样。正因为有了这个该井,内存优化表的统计信息管理方式和基于磁盘表的统计信息管理方式是一样的,而且也有一样的权衡。
1、是否需要更新统计信息的逻辑跟磁盘表的逻辑是一样的,但有一个例外:磁盘表的modify计数器mod-counter是在每个数据列里的,而内存优化表的mod-counter是在行级别的。Modify计数器通常用于跟踪表里面有多少数据发生了变化,一旦达到阀值自动更新统计信息功能就会启动。TF2453和(RECOMPILE重新编译)选项在表变量里得到支持。
2、支持AUTO_UPDATE_STATISTICS_ASYNC。
3、统计信息采样率跟基于硬盘的表一样,而且支持并行采样。
4、针对大部分统计信息改进,请确保数据库选项设置兼容级别为 130。
5、为了自动更新已存在的统计信息,需进行一次手动更新(见下面脚本)。
6、手动重新编译本地编译模块。使用sp_recompile重新编译本地编译模块。
统计信息的一次性脚本:  您可以运行一次下面的Transact-SQL脚本以更新所有内存优化表的统计信息,然后启用统计信息的自动更新(假设数据库已经开启AUTO_UPDATE_STATISTICS)。

-- Assuming AUTO_UPDATE_STATISTICS is already ON for your database:
-- ALTER DATABASE CURRENT SET AUTO_UPDATE_STATISTICS ON;
GO
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 130;
GO
DECLARE @sql NVARCHAR(MAX) = N‘‘;
SELECT
      @sql += NUPDATE STATISTICS 
         + quotename(schema_name(t.schema_id))
         + N.
         + quotename(t.name)
         + ; + CHAR(13) + CHAR(10)
   FROM sys.tables AS t
   WHERE t.is_memory_optimized = 1
;
EXECUTE sp_executesql @sql;
GO
-- Each row appended to @sql looks roughly like:
-- UPDATE STATISTICS [dbo].[MyMemoryOptimizedTable];

 



以上就是SQL Server 2016中In-Memory OLTP的新改进

以上是关于SQL Server 2016中In-Memory OLTP继CTP3之后的新改进的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server In-Memory OLTP Internals for SQL Server 2016

我才发现SQL Server 2016 RC1 已经发布

第九篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 cache table

In-Memory:内存数据库

第十篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 query

In-Memory:内存数据库