好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SQLServer中的临时表和表变量

在SQL Server的性能调优中,有一个不可比拟的问题:那就是如何在一段需要长时间的代码或被频繁调用的代码中处理 临时 数据集?表 变量 和 临时 表是两种选择。 记得在给一家国内首屈一指的海运公司作SQL Server应用性能评估和调优的时候就看到过大量的 临时


在SQL Server的性能调优中,有一个不可比拟的问题:那就是如何在一段需要长时间的代码或被频繁调用的代码中处理 临时 数据集?表 变量 和 临时 表是两种选择。

记得在给一家国内首屈一指的海运公司作SQL Server应用性能评估和调优的时候就看到过大量的 临时 数据集处理需求,而他们的开发人员就无法确定什么时候用 临时 表,什么时候用表 变量 ,因此他们就简单的使用了 临时 表。实际上 临时 表和表 变量 都有特定的适用环境。

先卖弄一些基础的知识:

表 变量

变量 都以@或@@为前缀,表 变量 是 变量 的一种,另外一种 变量 被称为标量(可以理解为标准 变量 ,就是标准数据类型的 变量 ,例如整型int或者日期型DateTime)。以@前缀的表 变量 是本地的,因此只有在当前用户会话中才可以访问,而@@前缀的表 变量 是全局的,通常都是系统 变量 ,比如说@@error代表最近的一个T-SQL语句的报错号。当然因为表 变量 首先是个 变量 ,因此它只能在一个Batch中生存,也就是我们所说的边界,超出了这个边界,表 变量 也就消亡了。

表 变量 存放在内存中,正是因为这一点所有用户访问表 变量 的时候SQL Server是不需要生成日志。同时 变量 是不需要考虑其他会话访问的问题,因此也不需要锁机制,对于非常繁忙的系统来说,避免锁的使用可以减少一部分系统负载。

表 变量 另外还有一个限制就是不能创建索引,当然也不存在统计数据的问题,因此在用户访问表 变量 的时候也就不存在执行计划选择的问题了(也就是以为着编译阶段后就没有优化阶段了),这一特性有的时候是件好事,而有些时候却会造成一些麻烦。

临时 表

临时 对象都以#或##为前缀, 临时 表是 临时 对象的一种,还有例如 临时 存储过程、 临时 函数之类的 临时 对象, 临时 对象都存储在tempdb中。以#前缀的 临时 表为本地的,因此只有在当前用户会话中才可以访问,而##前缀的 临时 表是全局的,因此所有用户会话都可以访问。 临时 表以会话为边界,只要创建 临时 表的会话没有结束, 临时 表就会持续存在,当然用户在会话中可以通过DROP TABLE命令提前销毁 临时 表。

我们前面说过 临时 表存储在tempdb中,因此 临时 表的访问是有可能造成物理IO的,当然在修改时也需要生成日志来确保一致性,同时锁机制也是不可缺少的。

跟表 变量 另外一个显着去别就是 临时 表可以创建索引,也可以定义统计数据,因此SQL Server在处理访问 临时 表的语句时需要考虑执行计划优化的问题
表 变量 vs. 临时 表 表 变量 临时 表 数据集的存储位置 内存(不考虑被换到页面文件这种情况) 磁盘(不考虑访问后被缓存到内存中) 是否需要日志 否 是 是否可以创建索引 否 是 是否可以使用统计数据 否 是 是否可以在多会话中访问 否 是 是否需要锁机制 否 是

结论

综上所述,大家会发现 临时 表和表 变量 在底层处理机制上是有很多差别的。

简单地总结,我们对于较小的 临时 计算用数据集推荐使用表 变量 。如果数据集比较大,如果在代码中用于 临时 计算,同时这种 临时 使用永远都是简单的全数据集扫描而不需要考虑什么优化,比如说没有分组或分组很少的聚合(比如说COUNT、SUM、AVERAGE、MAX等),也可以考虑使用表 变量 。使用表 变量 另外一个考虑因素是应用环境的内存压力,如果代码的运行实例很多,就要特别注意内存 变量 对内存的消耗。

一般对于大的数据集我们推荐使用 临时 表,同时创建索引,或者通过SQL Server的统计数据(Statisitcs)自动创建和维护功能来提供访问SQL语句的优化。如果需要在多个用户会话间交换数据,当然 临时 表就是唯一的选择了。需要提及的是,由于 临时 表存放在tempdb中,因此要注意tempdb的调优

本文作者:

查看更多关于SQLServer中的临时表和表变量的详细内容...

  阅读:34次