In-Memory:在内存中创建临时表和表变量
在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;
go CREATE 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 s
on temp.SpidFilter=s.session_id
and s<>@@spid
and s.session_id>50
where s.session_id is null; revert;
该脚本仅仅提供一种思路,在产品环境中,需要多测试,以防错误删除数据。
参考文档:
Memory-Optimized Table Variables
Faster temp table and table variable by using memory optimization
Improving temp table and table variable performance using memory optimization
Indexes for Memory-Optimized Tables
In-Memory:在内存中创建临时表和表变量的更多相关文章
- SQL Server中的临时表和表变量 Declare @Tablename Table
在SQL Server的性能调优中,有一个不可比面的问题:那就是如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择.记得在给一家国内首屈一指的海运公司作SQL Se ...
- SQL Server中的临时表和表变量
SQL Server中的临时表和表变量 作者:DrillChina出处:blog2008-07-08 10:05 在SQL Server的性能调优中,有一个不可比拟的问题:那就是如何在一段需要长时间的 ...
- sql server中的临时表、表变量和公用表表达式
在编写T-SQL语句的时候,SQL Server提供了三种方法临时存储某些结果集,分别是临时表.表变量和公用表表达式. 临时表 临时表需要在临时数据库TempDB中通过I/O操作来创建表结构,一旦用户 ...
- 【翻译】Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解)
[翻译]Anatomy of a Program in Memory—剖析内存中的一个程序(进程的虚拟存储器映像布局详解) . . .
- 在ORACLE存储过程中创建临时表
在ORACLE存储过程中创建临时表 存储过程里不能直接使用DDL语句,所以只能使用动态SQL语句来执行 --ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截 ...
- SQLServer中临时表与表变量的区别分析(转)
在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候去使用临时表而不使用表变量,有时候去使用表变量而不使用临时表呢? 临时表 临时表与永 ...
- SQLServer中临时表与表变量的区别分析
临时表 临时表与永久表相似,只是它的创建是在Tempdb中,它只有在一个数据库连接结束后或者由SQL命令DROP掉,才会消失,否则就会一直存在.临时表在创建的时候都会产生SQL Server的系统日志 ...
- SQLServer中临时表与表变量的区别分析【转】
在实际使用的时候,我们如何灵活的在存储过程中运用它们,虽然它们实现的功能基本上是一样的,可如何在一个存储过程中有时候去使用临时表而不使用表变量,有时候去使用表变量而不使用临时表呢? 临时表 临时表与永 ...
- [转]SQL Server中临时表与表变量的区别
[转]http://blog.csdn.net/skyremember/archive/2009/03/05/3960687.aspx 我们在数据库中使用表的时候,经常会遇到两种使用表的方法,分别就是 ...
随机推荐
- 基于ASP.NET/C#开发国外支付平台(Paypal)学习心得。
最近一直在研究Paypal的支付平台,因为本人之前没有接触过接口这一块,新来一家公司比较不清楚流程就要求开发两个支付平台一个是支付宝(这边就不再这篇文章里面赘述了),但还是花了2-3天的时间通 ...
- 深入理解 Java G1 垃圾收集器--转
原文地址:http://blog.jobbole.com/109170/?utm_source=hao.jobbole.com&utm_medium=relatedArticle 本文首先简单 ...
- 以向VS 程序打包集成自动写入注册表功能为例,介绍如何实现自由控制安装过程
最近由于项目部署时需要更灵活的控制程序安装的流程以及自定义安装行为,特意研究了一下VS程序打包,把解决办法和大家分享一下. 以VS2010为例: 这是一个已经设置好最基本的Visual Studio ...
- Effective前端2:优化html标签
div { float: left; } .keyboard > div + div { margin-left: 8px; } --> div{display:table-cell;ve ...
- [转载]强制不使用“兼容性视图”的HTML代码
在IE8浏览器以后版本,都有一个"兼容性视图",让不少新技术无法使用.那么如何禁止浏览器自动选择"兼容性视图",强制IE以最高级别的可用模式显示内容呢?下面就介 ...
- 在你的ASP.NET MVC中使用查找功能
在程序中,使用查找功能是少之不了.今天在ASP.NET环境下演示一回. 在cshtml视图中,有三个文本框,让用户输入关键词,然后点击最右连的“搜索”铵钮,如果有结果将显示于下面. Html: 表格放 ...
- 设计模式C#合集--单例模式
单例模式 代码: 第一种: private static Singleton singleton = null; private Singleton() { } public static Singl ...
- QT内省机制、自定义Model、数据库
本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...
- Netty5使用自签证书实现SSL安全连接
这次使用的Netty是最新的5.0 Alpha2版本,下载地址是:http://dl.bintray.com/netty/downloads/netty-5.0.0.Alpha2.tar.bz2,发布 ...
- API Monitor简介(API监控工具)
API Monitor是一个免费软件,可以让你监视和控制应用程序和服务,取得了API调用. 它是一个强大的工具,看到的应用程序和服务是如何工作的,或跟踪,你在自己的应用程序的问题. 64位支持 API ...