InMemory:在内存中创建临时表和表变量

Posted 悦光阴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了InMemory:在内存中创建临时表和表变量相关的知识,希望对你有一定的参考价值。

在Disk-Base数据库中,如果系统频繁地创建和更新临时表,大量的IO操作集中在tempdb中,tempdb很可能成为系统性能的瓶颈。在SQL Server 2016的内存(Memory-Optimized)数据库中,如果考虑使用内存优化结构来存储临时表,表变量,表值参数的数据,那么将完全消除IO操作的负载消耗,发挥大内存的优势,大幅提高数据库的性能。

在SQL Server 2016中,能够直接创建内存优化的表类型,表变量和表值参数的数据只存储在内存中;不能直接在内存中创建临时表,但是,SQL Server提供一个变通方法(Workaround),通过行级安全RLS(Row-Level-Security)控制,指定只有当前Session才能访问特定的数据,将内存优化表转换为Session级别的临时表,间接实现临时表的局部性和自动清空特性。

一,内存优化表类型(Memory-Optimized Table Type)

内存优化表类型定义的表变量,表值参数能够大幅提高效率(efficiency),有4个显著的特点:

  • 数据仅存储在内存中,在读写数据时,不会产生任何的IO消耗,消除了tempdb的竞争和利用率;
  • 必须有一个索引,Hash 或 Nonclustered 都行;每一个内存优化表必须创建一个索引;
  • 只需要指定启用内存优化:MEMORY_OPTIMIZED = ON,只持久化Schema;
  • 必须先创建表类型,后创建表值变量;

1,创建内存优化表类型

CREATE TYPE dbo.TypeTable  
AS TABLE  
(  
Column1  INT NOT NULL,  
Column2  VARCHAR(10) NOT NULL,
INDEX idxName NONCLUSTERED(Column1)
)  
WITH(MEMORY_OPTIMIZED = ON); 

2,创建内存优化表变量

declare @Table dbo.TypeTable 

二,创建“临时内存优化表”

在Disk-Base数据库中,局部临时表#temp的作用域是session,创建在tempdb中,一旦session生命周期结束,系统自动回收其存储空间。在SQL Server 2016中,不能直接在tempdb中创建内存优化表。要使用临时内存优化表,有一个变通的方法,在DB中创建内存优化表,通过Row-Level-Security控制Session能够访问的数据行,间接实现Session级别的临时表。

Step1,创建内存优化表,只持久化Table Schema

CREATE TABLE dbo.SessionTempTable  
(  
    Column1 INT NOT NULL,  
    Column2 NVARCHAR(4000) NULL,  
    SpidFilter SMALLINT NOT NULL DEFAULT (@@spid),  
    INDEX ix_SpidFiler NONCLUSTERED (SpidFilter),  
    --INDEX ix_SpidFilter HASH (SpidFilter) WITH (BUCKET_COUNT = 64),  
    CONSTRAINT CHK_soSessionC_SpidFilter CHECK ( SpidFilter = @@spid ),  
)  
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);  
go 

Step2,创建RLS,控制用户只能访问当前Session的数据

CREATE FUNCTION dbo.fn_SpidFilter
(@SpidFilter smallint)  
RETURNS TABLE  
WITH SCHEMABINDING , NATIVE_COMPILATION  
AS  
RETURN  
    SELECT 1 AS fn_SpidFilter  
    WHERE @SpidFilter = @@spid;  
go

CREATE SECURITY POLICY dbo.soSessionC_SpidFilter_Policy  
ADD FILTER PREDICATE dbo.fn_SpidFilter(SpidFilter)  
ON dbo.SessionTempTable  
WITH (STATE = ON);  
go 

Step3,使用内存优化临时表

  • 表名替换:使用 dbo.Temp 代替 #Temp;
  • 不能创建和删除临时表
    • 移除代码“create table #temp”,使用“delete from dbo.Temp”子句取代,将旧数据清空;
    • 移除代码“drop table #temp”,建议使用 “delete from dbo.Temp” 子句,在当前Session结束前将当前Session产生的数据清空,节省内存空间;

虽然临时表的使用和管理有点麻烦,但是,这点麻烦和大幅的性能提升来比,微不足道,建议使用内存优化表来代替临时表,体验飞一般的速度。

 

参考文档:

Faster temp table and table variable by using memory optimization

Improving temp table and table variable performance using memory optimization

CREATE TYPE (Transact-SQL)

Indexes for Memory-Optimized Tables

以上是关于InMemory:在内存中创建临时表和表变量的主要内容,如果未能解决你的问题,请参考以下文章

避免在内存中创建多个代码副本

SQL Server 中的临时表和表变量有啥区别?

SQL Server 临时表和表变量系列之选择篇

插入临时表和表变量时的结果不同

mysql 内存表和一般表的区别

MySQL中堆表和临时表的区别?