SQLServer数据库之试试SQLServer 2014的内存优化表
小标 2019-03-20 来源 : 阅读 1165 评论 0

摘要:本文主要向大家介绍了SQLServer数据库之试试SQLServer 2014的内存优化表,通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。

本文主要向大家介绍了SQLServer数据库之试试SQLServer 2014的内存优化表,通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。

SQLServer数据库之试试SQLServer 2014的内存优化表

SQL Server2014存储引擎:行存储引擎,列存储引擎,内存引擎

SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度。

现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技术来支持大规模OLTP工作负载。

就算如此,要利用此新功能,数据库必须包含“内存优化”文件组和表

即所配置的文件组和表使用Hekaton技术。

幸运的是,SQL Server 2014使这一过程变得非常简单直接。

要说明其工作原理,我们来创建一个名为TestHekaton的数据库,然后添加一个内存优化文件组到此数据库

 

测试环境:Microsoft Azure 大陆版 虚拟机

4核 ,7G内存,Windows2012R2

SQLSERVER2014企业版



实验

第一个实验:内存表的简单使用

 

步骤1:创建数据库和MEMORY_OPTIMIZED_DATA文件组


USE master;GOCREATE DATABASE TestHekaton;GOALTER DATABASE TestHekatonADD FILEGROUP HekatonFG CONTAINS MEMORY_OPTIMIZED_DATA;GO


注意ALTER DATABASE语句中的ADD FILEGROUP 语句包含文件组的名称(HekatonFG)和关键字CONTAINS MEMORY_OPTIMIZED_DATA

它会指导SQL Server去创建支持内存OLTP引擎所必需的文件组类型。

注意:每个数据库只能有一个MEMORY_OPTIMIZED_DATA文件组!!

要确认此文件组已经创建,可以访问SSMS中数据库属性的Filegroups 界面,如下图所示。


步骤2:

添加一个存放数据文件的文件夹到文件组,可以通过ALTER DATABASE语句来实现。

添加一个存放内存优化表数据的文件夹到HekatonFG文件组:


--执行下面语句之后会在C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA路径下创建一个文件夹--文件夹名为HekatonFile--请不要预先创建好这个文件夹ALTER DATABASE TestHekatonADD FILE(   NAME = 'HekatonFile',   FILENAME ='C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\HekatonFile')TO FILEGROUP [HekatonFG];GO


注意:在ADD FILE 语句中,我们只为文件路径提供了一个友好的名称。

并且,在TO FILEGROUP 语句中,指定刚才新建的文件组名字

然后可以去往数据库属性的 Files 界面来查看刚刚添加的文件,如图所示。


比如是这样


ALTER DATABASE [test99]ADD FILE(   NAME = 'HekatonFile',   FILENAME ='D:\DataBase\xtp\')TO FILEGROUP [HekatonFG];GO


步骤3:

在为数据库设置了必需的文件组和文件之后,就可以创建自己的内存优化表了。

当在定义表的时候,会指定其“持久性”

一个内存优化表可以是持久的非持久的

(1)对于一个持久表是将数据存储在内存中,而且也保存在内存优化文件组中。

(2)对于一个非持久表,数据是仅存储在内存中的,所以,如果系统崩溃或重启,数据就会丢失。

 

在SQL Server 2014中默认用的是持久表,接下来我们来深入了解一下。

当定义一个持久内存优化表的时候,你还必须定义一个基于非聚集哈希索引的主键。

在一个哈希索引中,数据是通过一个内存散列表进行访问的,而非固定大小页。

哈希索引是在内存优化表中唯一支持的索引类型。

除了在表定义中定义主键外,还必须将表配置为内存优化的,如下CREATE TABLE 语句所示:


USE TestHekaton;GOCREATE TABLE Reseller    (      [ResellerID] INT NOT NULL                       PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1024),      [ResellerName] NVARCHAR(50) NOT NULL ,      [ResellerType] NVARCHAR(20) NOT NULL    )WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);INSERT  INTO ResellerVALUES  ( 1, 'A Bike Store', 'Value Added Reseller' );


ResellerID 字段包含了定义为非聚集哈希的主键。

注意,必须包含一个WITH 语句来指定BUCKET_COUNT 的设置,它表明了在哈希索引中应该创建的bucket数量。

(每个bucket是一个槽,可以用来存放一组键值对。)

微软建议bucket的数量应是一到两倍于你所期望的表所要包含的唯一索引键的数量。

由于每个数据库只能有一个MEMORY_OPTIMIZED_DATA文件组,所以创建表的时候就不需要指定表创建在哪个MEMORY_OPTIMIZED_DATA文件组了

 

此表定义以第二个WITH 语句结束。

这里你指定MEMORY_OPTIMIZED 选项为ON 以及DURABILITY 选项为SCHEMA_AND_DATA,此选项是针对持久表的。

接着在表中插入一条记录,这样就可以进行测试了。

数据已经插入到表中

 

这就是创建一个内存优化表的全部步骤。

但是,要记住,SQL Server 2014对这些表有着很多限制。例如,它们不支持外键约束检查(感觉类似于MySQL的memory存储引擎),

它们也不支持IDENTITY 字段或DML触发器。最为重要的是,内存耗尽会导致数据写入失败。

 

步骤4:

另一方面,内存优化表支持本地编译存储过程,只要那些存储过程只引用内存优化表。

在这种情况下,存储过程可以转化为本地代码native code,这样会执行更快且要比典型存储过程需要更少的内存。

除了只引用内存优化表,一个本地编译存储过程必须是模式绑定的并运行在一个特定执行内容内。

另外,每个本地编译存储过程必须完全由一个原子块组成。

 

下面的CREATE PROCEDURE 语句定义了一个本地编译存储过程,它从前面所创建的Reseller表中检索数据


CREATE PROCEDURE GetResellerType ( @id INT )    WITH NATIVE_COMPILATION,         SCHEMABINDING,         EXECUTE AS OWNERAS    BEGIN  ATOMIC WITH(TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'us_english')        SELECT  ResellerName ,                ResellerType        FROM    dbo.Reseller        WHERE   ResellerID = @id    END;GO


在定义了参数之后,包含一个WITH 语句来指定NATIVE_COMPILATION 选项。

注意:此语句还包含SCHEMABINDING 选项和EXECUTE AS 选项,以及指定了OWNER 作为执行环境。

而WITH 语句负责实现本地编译存储过程的三大需求。

要解决原子块需求,可以在BEGIN 关键字后指定ATOMIC ,之后是另一个包含有事务隔离级别和语言的WITH 语句。

对于访问内存优化表的事务,可以使用SNAPSHOT,REPEATABLEREAD 或SERIALIZABLE 作为隔离级别

而且,对于此语言必须使用一个可用的语言或语言别名。

这是在定义存储过程时所需要包含的全部内容。一旦创建,就可以通过执行EXECUTE 语句来对其加以测试,如下例中所示:

EXEC GetResellerType 1;

 

此语句会返回经销商的姓名和类型,在本例中分别是ABike Store和Value Added Reseller。


内存优化表不使用 TempDB 来存储行版本,所以使用内存优化表不用担心tempdb数据库会暴增。

 

即使没有打开snapshot隔离级别,内存优化表默认会开启snapshot隔离级别,对内存优化表的访问使用的都是snapshot隔离级别

事务不会对内存优化表使用锁和闩锁,但是又可以默认使用snapshot隔离级别保证数据一致性,这是内存表的强大之处


use [test99]/****** Script for SelectTopNRows command from SSMS  ******/SELECT TOP 1000 [ResellerID]      ,[ResellerName]      ,[ResellerType]  FROM [test99].[dbo].[Reseller] WITH (SNAPSHOT) where [ResellerID]>0 and [ResellerID] <60



第一个实验:内存表的数据查询速度比较

聚集索引表和内存优化表的比较

建表语句


USE TestHekaton;GO--内存优化表CREATE TABLE testmemory1    (      [ID] FLOAT NOT NULL                       PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1024),      [Name] NVARCHAR(50) NOT NULL     )WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);


USE TestHekaton;GO--聚集索引表CREATE TABLE testmemory2    (      [ID] FLOAT NOT NULL PRIMARY KEY,      [Name] NVARCHAR(50) NOT NULL     )


---------------------------------------------------------------

插入性能比较

内存优化表

SET STATISTICS IO ON SET STATISTICS TIME ONINSERT into testmemory1([id],[name])  SELECT [id] ,[name] from sysobjectsSET STATISTICS IO OFFSET STATISTICS TIME OFF


Table 'sysschobjs'. Scan count 1, logical reads 33, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 20 ms.(90 row(s) affected) SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms.


聚集索引表

SET STATISTICS IO ON SET STATISTICS TIME ONINSERT into testmemory2([id],[name])  SELECT [id] ,[name] from sysobjectsSET STATISTICS IO OFFSET STATISTICS TIME OFF


Table 'testmemory2'. Scan count 0, logical reads 183, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.Table 'sysschobjs'. Scan count 1, logical reads 33, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 10 ms.(90 row(s) affected) SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms.


-------------------------------------------------------------------------------

查询性能比较

内存优化表

SET STATISTICS IO ON SET STATISTICS TIME ONSELECT * FROM  testmemory1  ORDER BY [ID] DESCSET STATISTICS IO ONSET STATISTICS TIME ON


SQL Server parse and compile time:    CPU time = 0 ms, elapsed time = 1 ms. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms.(90 row(s) affected) SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms.


聚集索引表

SET STATISTICS IO ON SET STATISTICS TIME ONSELECT * FROM  testmemory2  ORDER BY [ID] DESCSET STATISTICS IO ONSET STATISTICS TIME ON


(91 row(s) affected)Table 'testmemory2'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms. SQL Server Execution Times:   CPU time = 0 ms,  elapsed time = 0 ms.


可以看到内存优化表读写数据(insert 、select)的时候都看不到IO读写

 

补充测试:

 

我们先删除刚才插入的数据,内存优化表是不支持truncate table的,只能用delete from 表


只能够delete


插入测试

内存优化表


聚集索引表


 -------------------------------------------------------------------------------------------------

查询测试

内存优化表


聚集索引表



我们看一下事务日志


CHECKPOINTGOSELECT Context ,Operation,AllocUnitNameFROM sys.fn_dblog(NULL, NULL)


ContextOperationAllocUnitName
LCX_NULLLOP_HKNULL
LCX_NULLLOP_HK_CHAINEDNULL
LCX_NULLLOP_HKNULL
LCX_NULLLOP_HK_CHAINEDNULL
LCX_NULLLOP_HK_CHECKPOINTNULL
LCX_NULLLOP_HKNULL
LCX_NULLLOP_BEGIN_XACTNULL
LCX_NULLLOP_FS_DOWNLEVEL_OPNULL
LCX_NULLLOP_BEGIN_XACTNULL
LCX_CLUSTEREDLOP_INSERT_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_INDEX_LEAFLOP_INSERT_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_NULLLOP_COMMIT_XACTNULL
LCX_MARK_AS_GHOSTLOP_DELETE_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_MARK_AS_GHOSTLOP_DELETE_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_NULLLOP_HKNULL
LCX_NULLLOP_FS_DOWNLEVEL_OPNULL
LCX_HEAPLOP_INSERT_ROWSsys.xtp_storage
LCX_INDEX_LEAFLOP_INSERT_ROWSsys.xtp_storage.UQ__xtp_stor__3213E83EA8737D06
LCX_CLUSTEREDLOP_EXPUNGE_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_CLUSTEREDLOP_EXPUNGE_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_PFSLOP_SET_BITSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_INDEX_LEAFLOP_EXPUNGE_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_INDEX_LEAFLOP_EXPUNGE_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_NULLLOP_COMMIT_XACTNULL
LCX_NULLLOP_BEGIN_XACTNULL
LCX_NULLLOP_FS_DOWNLEVEL_OPNULL
LCX_NULLLOP_BEGIN_XACTNULL
LCX_CLUSTEREDLOP_INSERT_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_INDEX_LEAFLOP_INSERT_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_NULLLOP_COMMIT_XACTNULL
LCX_MARK_AS_GHOSTLOP_DELETE_ROWSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_PFSLOP_SET_BITSsys.filestream_tombstone_2073058421.FSTSClusIdx
LCX_MARK_AS_GHOSTLOP_DELETE_ROWSsys.filestream_tombstone_2073058421.FSTSNCIdx
LCX_NULLLOP_FS_DOWNLEVEL_OPNULL
LCX_HEAPLOP_INSERT_ROWS

本文由职坐标整理并发布,希望对同学们学习SQL Server有所帮助,更多内容请关注职坐标数据库SQL Server数据库频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程