最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

表变量临时表

来源:动视网 责编:小OO 时间:2025-09-29 06:31:08
文档

表变量临时表

在SQLServer的性能调优中,如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。开发人员就无法确定什么时候用临时表,什么时候用表变量,因此就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。表变量变量都以@或@@为前缀,表变量是变量的一种,另外一种变量被称为标量(可以理解为标准变量,就是标准数据类型的变量,例如整型int或者日期型DateTime)。以@前缀的表变量是本地的,因此只有在当前用户会话中才可以访问,而@@前缀的表变量是全局的,通常
推荐度:
导读在SQLServer的性能调优中,如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。开发人员就无法确定什么时候用临时表,什么时候用表变量,因此就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。表变量变量都以@或@@为前缀,表变量是变量的一种,另外一种变量被称为标量(可以理解为标准变量,就是标准数据类型的变量,例如整型int或者日期型DateTime)。以@前缀的表变量是本地的,因此只有在当前用户会话中才可以访问,而@@前缀的表变量是全局的,通常
在SQL Server的性能调优中,如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。开发人员就无法确定什么时候用临时表,什么时候用表变量,因此就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。

表变量

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

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

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

临时表

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

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

跟表变量另外一个显著去别就是临时表可以创建索引,也可以定义统计数据,因此SQL Server在处理访问临时表的语句时需要考虑执行计划优化的问题。

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

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

进一部探讨:

临时表

临时表存储在TempDB数据库中,所有的使用此SQL Server 实例的用户都共享这个TempDB,因为我们应该确保用来存储TempDB数据库的硬盘有足够的空间,以使之能够自己的增长.最好能够存储在一个拥有硬盘控制器上.因为这样不存在和其它的硬盘I/O进行争用.

很多程序员认为临时表非常危险,因为临时表有可能被多个连接所共享.其实在SQL Server中存在两种临时表:局部临时表和全局临时表,局部临时表(Local temp table)以#前缀来标识,并且只能被创建它的连接所使用.全局临时表(Global temp table)以##前缀来进行标识,并且可以和其它连接所共享.

局部临时表

局部临时表不能够被其它连接所共享的原因其实是在SQL Server 2000中自动为局部临时表的表名后面加上了一个唯一字符来标识.如:

CREATE TABLE [#DimCustomer_test]

(

  [CustomerKey] [int],[FirstName] [nvarchar](50),[MiddleName] [nvarchar](50),[LastName] [nvarchar](50)

)

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表#DimCustomer_test已经被加上了后缀:

USE TempDB

GO

SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

the Result is:

#DimCustomer_test___________________________________________________________________________________________________000000000005

全局临时表

CREATE TABLE [##DimCustomer_test]

(

 [CustomerKey] [int],

 [FirstName] [nvarchar](50),  

 [MiddleName] [nvarchar](50),  

 [LastName] [nvarchar](50),

)

现在我们来查看一下TempDB中 sysobjects表,我们会发现我们新创建的临时表##DimCustomer_test没有被加上了后缀:

USE TempDB

GO

SELECT name FROM sysobjects WHERE name LIKE ’%DimCustomer%’

The Result are:

##DimCustomer_test

可以看到我们刚才创建的全局临时表名字并没有被加上标识.

表变量

表变量和临时表针对我们使用人员来说并没有什么不同,但是在存储方面来说,他们是不同的,表变量存储在内存中.所以在性能上和临时表相比会更好些! 另一个不同的地方是在表连接中使用表变量时,要为此表变量指定别名.如:

USE AdventureWorksDW

GO

DECLARE @DimCustomer_test TABLE

(

[CustomerKey] [int] ,

[FirstName] [nvarchar](50) , 

[MiddleName] [nvarchar](50) , 

[LastName] [nvarchar](50) ,

)

INSERT @DimCustomer_test

( [CustomerKey],[FirstName],[MiddleName],[LastName] ) SELECT   [CustomerKey],[FirstName] ,[MiddleName],[LastName]  FROM DimCustomer

SELECT [@DimCustomer_test].CustomerKey,SUM(FactInternetSales.OrderQuantity)

FROM @DimCustomer_test   INNER JOIN FactInternetSales  ON

@DimCustomer_test.CustomerKey = FactInternetSales.CustomerKey

Group BY CustomerKey

Result:

Server: Msg 137, Level 15, State 2, Line 32

Must declare the variable

如果我们对上面的查询进行更改,对查询使用别名(并且找开IO):

DECLARE @DimCustomer_test TABLE

(

[CustomerKey] [int] ,

[FirstName] [nvarchar](50) , 

[MiddleName] [nvarchar](50) , 

[LastName] [nvarchar](50) ,

)

INSERT @DimCustomer_test

( [CustomerKey],[FirstName],[MiddleName],[LastName] ) SELECT   [CustomerKey],[FirstName] ,[MiddleName],[LastName]  FROM DimCustomer

SELECT t.CustomerKey,f.OrderQuantity

FROM @DimCustomer_test as t INNER JOIN FactInternetSales   f ON

t.CustomerKey = f.CustomerKey

表变量在批处理结束时自动被系统删除,所以你不必要像使用临时表表一样显示的对它进行删除.

--查询库里面是否存在该临时表,有则drop

IF EXISTS(select * from tempDB..sysobjects  where name like '%#tempChangeDrugs%'  and  xtype='U')

DROP TABLE #tempChangeDrugs;

--sql2008,sql2005的写法 查询库里面表名类似ConsumeRecord的表

SELECT name FROM sys.tables where name like '%ConsumeRecord%'

--sql2000的写法

select name from ..sysobjects  where name like '%ConsumeRecord%'  and  xtype='U'

多个用户访问数据库,使用临时表也没关系,因为局部临时表在建立的时候,SQL已经为不同用户生成的不同的临时表,drop也是相应的临时表,不会有冲突,但是如果用的是全局的临时表就有可能会有问题。

表变量也不会有问题,因为它也是局部变量。

临时表存储在TempDB数据库中,所有的使用此SQL Server 实例的用户都共享这个TempDB,因为我们应该确保用来存储TempDB数据库的硬盘有足够的空间,以使之能够自己的增长.最好能够存储在一个拥有硬盘控制器上.因为这样不存在和其它的硬盘I/O进行争用. 

在SQL Server中存在两种临时表:局部临时表和全局临时表,局部临时表(Local temp table)以#前缀来标识,并且只能被创建它的连接所使用.全局临时表(Global temp table)以##前缀来进行标识,并且可以和其它连接所共享.

文档

表变量临时表

在SQLServer的性能调优中,如何在一段需要长时间的代码或被频繁调用的代码中处理临时数据集?表变量和临时表是两种选择。开发人员就无法确定什么时候用临时表,什么时候用表变量,因此就简单的使用了临时表。实际上临时表和表变量都有特定的适用环境。表变量变量都以@或@@为前缀,表变量是变量的一种,另外一种变量被称为标量(可以理解为标准变量,就是标准数据类型的变量,例如整型int或者日期型DateTime)。以@前缀的表变量是本地的,因此只有在当前用户会话中才可以访问,而@@前缀的表变量是全局的,通常
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top