在Disk-Base数据库中,由于临时表和表变量的数据存储在tempdb中,如果系统频繁地创建和更新临时表和表变量,大量的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的数据

推荐为Predicate function 和 Security Policy创建单独的Schema,然后在该Schema下创建Predicate function 和 Security Policy,对于Predicate function必须使用 NATIVE_COMPLIATION选项创建。

create schema rls
authorization dbo;CREATE FUNCTION rls.fn_SpidFilter
(@SpidFilter smallint)
RETURNS TABLE
WITH SCHEMABINDING , NATIVE_COMPILATION
AS
RETURN  SELECT 1 AS fn_SpidFilter  WHERE @SpidFilter = @@spid;
goCREATE SECURITY POLICY rls.soSessionC_SpidFilter_Policy
ADD FILTER PREDICATE rls.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产生的数据清空,节省内存空间;

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

三,维护

1,通过RLS来创建内存临时表,如何清理临时表占用的内存空间?

试想出现异常,在当前Session将海量数据插入到临时表之后,Session异常终止,此时,Session没有来得及清空(Purge)临时表中的数据,这些数据仍然驻留在内存中。如果这种异常出现的频率很高,那么会导致内存优化表消耗大量的系统内存,必须有机制来定期清理临时表占用的内存空间。

step1,创建一个用户,RLSAdmin,授予db_owner的权限

--create User
create user RLSAdmin without login;
alter role db_owner
add member RLSAdmin;
go

step2,修改Predicate Function,如果用户是RLSAdmin,允许访问Base Table的所有数据行;

--create predicate function
CREATE FUNCTION rls.fn_SpidFilter
(@SpidFilter smallint)
RETURNS TABLE
WITH SCHEMABINDING , NATIVE_COMPILATION
AS
RETURN  SELECT 1 AS fn_SpidFilter  WHERE @SpidFilter = @@spid or User_Name()='RLSAdmin';
go

step3,创建Schedule,定期检查数据库中的临时表,如果发现临时表中的存在未被清理的无效数据,那么删除该部分数据,释放内存。

execute as RLSAdmin;delete temp
from dbo.SessionTempTable temp
left join sys.dm_exec_sessions son temp.SpidFilter=s.session_id and s<>@@spid and s.session_id>50
where s.session_id is null; revert;

该脚本仅仅提供一种思路,在产品环境中,需要多测试,以防错误删除数据。

转载于:https://www.cnblogs.com/chenliyang/p/6548231.html

在内存中创建临时表和表变量相关推荐

  1. SqlServer 中的临时表与表变量

    我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是使用临时表及表变量.在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候 ...

  2. [导入]SQL中的临时表和表变量

    我们经常使用临时表和表变量,那现在我们就对临时表和表变量进行一下讨论. 临时表 局部临时表 全局临时表 表变量 临时表 临 时表存储在TempDB数据库中,所有的使用此SQL Server 实例的用户 ...

  3. sql 表变量 临时表_SQL表变量概述

    sql 表变量 临时表 This article explores the SQL Table variables and their usage using different examples. ...

  4. 关于临时表和表变量的差别1

    临时表,表变量,这2个兄弟在平时使用的时候并不会陌生.很多时候我们都借用这2兄弟来进行一下中间结果集的缓存之类的功能.那我就简单说下这2兄弟在查询时候的一些小区别 1.首先我建立了一个表,存放100W ...

  5. SQL Server中临时表与表变量的区别

    我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是使用临时表及表变量.在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候 ...

  6. SQL Server--[转]SQL Server中临时表与表变量的区别

    http://blog.csdn.net/skyremember/archive/2009/03/05/3960687.aspx 我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是使用临 ...

  7. php sql server临时表,SQLServer中临时表与表变量的区别分析

    在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候去使用临时表而不使用表变量,有时候去使用表变量而不使用临时表呢? 临时表 临时表与永 ...

  8. sql语句用变量替换表名_使用内存优化表替换SQL临时表和表变量

    sql语句用变量替换表名 TempDB usage can be considered as a performance bottleneck for workloads that use SQL t ...

  9. 存储过程中引用的常规表,临时表以及表变量是否会导致存储过程的重编译

    在存储过程中,经常要引用一些表来存储一些中间数据,用完即删.对于这个中间表,用常规表,临时表或者表变量有什么区别呢? 下面我们看一下这三种中间表是否会造成执行计划的重编译. 首先打开sql serve ...

最新文章

  1. nginx--之静态服务器
  2. 【Tools】git提示“warning: LF will be replaced by CRLF”的解决办法
  3. 2019 ACM-icpc西安邀请赛总结(无题解)
  4. 大数据开发实战:数据仓库技术
  5. Excel,Python,SQL?数据分析师的技能树要怎么点?
  6. 互联网晚报 | 2月21日 星期一 | 北京冬奥会闭幕;天猫将新增菜鸟驿站送货上门服务;上汽奥迪首款电动车型开启预售...
  7. Java笔记-对称加密AES的使用
  8. 对当今社会的某些现象的感想
  9. JavaScript读写.txt文档 - 方法篇
  10. 深度学习(三十三)CRF as RNN语义分割-未完待续
  11. python爬取b站评论_学习笔记(1):写了个python爬取B站视频评论的程序
  12. 12. No More MVC
  13. html微信窗口阻止滚动条,微信浏览器禁止页面下拉查看网址(不影响页面内部scroll)...
  14. Todesk一直显示正在连接本地连接
  15. JavaScript 数据结构与算法(队列)
  16. SVC(可分层视频编解码)
  17. 长安链源码学习--提案(Proposer)(五)
  18. MATLAB画图并将两个图排列在一起
  19. Radius/Free Radius/Diameter协议
  20. 基于多特征的技术融合关系预测及其价值评估

热门文章

  1. c程序员的python开发总结
  2. .net 中debug 微软内部代码
  3. 如何找回系统盘丢失的空间
  4. Android中DisplayMetrics 获取手机屏幕分辨率
  5. Project Life Cycle
  6. 血的教训--如何正确使用线程池submit和execute方法
  7. shutil——高级的 文件、文件夹、压缩包 处理模块
  8. 刷题总结——树的同构(bzoj4337 树上hash)
  9. Go之Channel
  10. Struts hibernate Spring 框架原理