表变量存储在内存中,而临时表存储在tempdb中,会涉及到物理IO读写,那么咱们是否能够由此得出结论,使用表变量要比使用临时表效率高呢?相信有一部分人会和我有一样的想法,使用表变量的效率高,真是如此吗?先从一次优化存储过程的经历提及。sql
存储过程涉及到两个表,一个是用户今日积分表@tableUserScore(数据源来自用户积分详情表中的今日数据),一个是用户积分统计表UserScoreSum,该存储过程逻辑就是统计@tableUserScore中用户不一样缘由的积分值,生成到表UserScoreSum中。数据量不算很大,@tableUserScore中大概40万条,但这个存储过程执行时间却有些惊人,一般都在1个小时之上。优化的最终结果是将表变量@tabeUserScore换成了临时表#tableUserScore,并在userid和reason上添加了联合索引,优化的效果是执行时间控制在了40S左右。临时表和表变量效率相差百倍,此次优化经历让我对临时表和表变量有了从新认识,也有了一连串的疑问,它们是如何存储的,效率如何,如何选用?数据库
declare @tableUserScore table( userid int, --用户编号 name varchar(10), --用户姓名 reason varchar(32), --积分缘由 score int --积分值 ) create table UserScoreSum( userid int, --用户编号 name varchar(10), --用户姓名 createTime datetime, --时间 reason1Score int, --缘由1积分值 reason2Score int, --缘由2积分值 reason3Score int, --缘由3积分值 reason4Score int, --缘由4积分值 )
如下是我的翻阅资料后的理解,总结出来但愿能给和我有一样认识的人提个醒,起到抛砖引玉的做用,也但愿你们对理解错误之处提出指正。性能
临时表大数据
临时表有两种类型:本地表和全局表。在与首次建立或引用表时相同的 SQL Server 实例链接期间,本地临时表只对于建立者是可见的。当用户与 SQL Server 实例断开链接后,将删除本地临时表。全局临时表在建立后对任何用户和任何链接都是可见的,当引用该表的全部用户都与 SQL Server 实例断开链接后,将删除全局临时表。本地临时表的名称都是以“#”为前缀,全局临时表的名称都是以“##”为前缀。优化
临时表存储在tempdb中,所以临时表的访问是有可能形成物理IO的,固然在修改时也须要生成日志来确保一致性,同时锁机制也是不可缺乏的。spa
临时表能够建立索引,也能够定义统计数据,因此能够用数据定义语言(DDL)的声明来阻止临时表添加的限制,约束,并参照完整性,如主键和外键约束。日志
表变量code
表变量是变量的一种,表变量也分为本地及全局的两种,本地表变量的名称都是以“@”为前缀,只有在本地当前的用户链接中才能够访问。全局的表变量的名称都是以“@@”为前缀,通常都是系统的全局变量,像咱们经常使用到的,如@@Error表明错误的号,@@RowCount表明影响的行数。orm
表变量存放在内存中,正是由于这一点全部用户访问表变量的时候SQL Server是不须要生成日志。同时变量是不须要考虑其余会话访问的问题,所以也不须要锁机制,对于很是繁忙的系统来讲,避免锁的使用能够减小一部分系统负载。[表变量存放在内存是有必定限制的,若是表变量数据量超过阈值,会把内存耗尽,而后使用TempDB的空间,这样主要仍是使用硬盘空间,但同时把内存基本耗尽,增长了内存调入调出的机会,反而下降速度]索引
表变量另外还有一个限制就是不能建立索引,固然也不存在统计数据的问题,所以在用户访问表变量的时候也就不存在执行计划选择的问题了(也就是觉得着编译阶段后就没有优化阶段了),这一特性有的时候是件好事,而有些时候却会形成一些麻烦。
临时表 vs. 表变量
1.存储位置:临时表是利用了硬盘(tempdb数据库) ,表名变量是占用内存,所以小数据量固然是内存中的表变量更快。当大数据量时,就不能用表变量了,太耗内存了。大数据量时适合用临时表。
2.性能:不能一律而论,表变量存储数据有个性能临界点,在这个临界点以内,表变量比临时表快,表变量是存储在内存中的。
3.索引:表变量不支持索引和统计数据,但能够有主键;临时表则能够支持索引和统计数据。
咱们对于较小的临时计算用数据集考虑使用表变量。若是数据集比较大,若是在代码中用于临时计算,同时这种临时使用永远都是简单的全数据集扫描而不须要考虑什么优化,好比说没有分组或分组不多的聚合(好比说COUNT、SUM、AVERAGE、MAX等),也能够考虑使用表变量。使用表变量另一个考虑因素是应用环境的内存压力,若是代码的运行实例不少,就要特别注意内存变量对内存的消耗。通常对于大的数据集咱们最好使用临时表,同时建立索引。