首页 > 代码库 > InMemory:在内存中创建临时表和表变量

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;  goCREATE 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:在内存中创建临时表和表变量