Table变量和临时表区别

转载From :http://hmyhuo1983.blog.163.com/blog/static/53819619200963123116205/

 

//声明临时表

  CREATE table #T (s varchar(128))

//声明Table变量

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客DECLARE @T table (s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客INSERT into #T select 'old value #'

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客INSERT into @T select 'old value @'

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客BEGIN transaction

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  UPDATE #T set s='new value #'

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  UPDATE @T set s='new value @'

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客ROLLBACK transaction

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SELECT * from #T

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SELECT * from @T

 

s             

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客---------------

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客old value #

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客s                

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客---------------

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客new value @</PRE>

//声明table变量

declare     @table   table   (tid   int,tvalue   varchar(20))    
        insert   into   @table  
        values(100,'test')       
       insert   into   @table  
       select   tid   ,tvalue   from   @table
  

这行代码一目了然,临时表能起到事务回滚的作用,但是table变量不可以.作者解释是table变量不在事务作用范围之内.所以当table变量即使遇到回滚命令,但是也不会真的执行回滚.

区别二:

任何含有临时表的存储过程是不能被预编译的.这在一个很长的存储过程中,优势会更加凸显.

区别三:

table变量作为变量只能在同范围内存在,不可能跨范围.还有就是table变量在内置的存储过程中或者exec(string)语句中是不可见的还有就是不能被用于INSERT/EXEC statements.

 

下面的例子我来演示如何对比临时表和table变量在存储过程中预编译的区别.

创建一个测试表:

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREATE table NUM (n int primary key, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SET nocount on

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客DECLARE @n int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SET @n=1000000

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客WHILE @n>0 begin

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    SELECT @n,'Value: '+convert(varchar,@n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SET @n=@n-1

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  END

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

然后创建存储过程:T1

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREATE procedure T1

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  @total int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客AS

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  CREATE table #T (n int, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into #T select n,s from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n%100>0 and n<=@total

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @res varchar(128)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SELECT @res=max(s) from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n<=@total and

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      NOT exists(select * from #T

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      WHERE #T.n=NUM.n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

这个存储过程的参数@Total给定的越大,那么执行的时间越长.

为精确测量存储过程执行时间,我使用了以下代码:

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客DECLARE @t1 datetime, @n int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SET @t1=getdate()

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SET @n=100 – (**)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客WHILE @n>0 begin

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  EXEC T1 1000 – (*)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SET @n=@n-1 end

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客SELECT datediff(ms,@t1,getdate())

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

(*) 是存储过程参数.

现在我们给这个存储过程来第一次提速:个它加个主键

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREATE procedure T2

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  @total int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客AS

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  CREATE table #T (n int primary key, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into #T select n,s from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n%100>0 and n<=@total

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @res varchar(128)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SELECT @res=max(s) from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n<=@total and

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      NOT exists(select * from #T

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      WHERE #T.n=NUM.n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

在下面的对比中你可以发现已经大大的提速了.

然后再来一次提速:给它加个聚集索引

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREATE procedure T3

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  @total int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客AS

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  CREATE table #T (n int, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into #T select n,s from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n%100>0 and n<=@total

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  CREATE clustered index Tind on #T (n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @res varchar(128)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SELECT @res=max(s) from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n<=@total and

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      NOT exists(select * from #T

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      WHERE #T.n=NUM.n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

很惊讶速度已经提高了很多!

那好了,咱们再来测试一下table变量的速度吧

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREARE procedure V1

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  @total int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客AS

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @V table (n int, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into @V select n,s from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n%100>0 and n<=@total

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @res varchar(128)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SELECT @res=max(s) from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n<=@total and

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      NOT exists(select * from @V V

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      WHERE V.n=NUM.n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO

然后再来创建一个有主键的:

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客CREATE procedure V2

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  @total int

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客AS

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @V table (n int primary key, s varchar(128))

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  INSERT into @V select n,s from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n%100>0 and n<=@total

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  DECLARE @res varchar(128)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客  SELECT @res=max(s) from NUM

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客    WHERE n<=@total and

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      NOT exists(select * from @V V

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客      WHEREre V.n=NUM.n)

Table变量和临时表区别 - 书山有路 - hmyhuo1983的博客GO<

然后咱们来看看我测试的结果吧!

 

Table 1, using SQL Server 2000, time in ms

 

Records

T1T2T3V1V2
100.7113.50.60.8
1001.21.714.21.21.3
10007.15.52775.3
100007257827148
100000883480580840510
1000000450566090152202024012010

But the real shock is when you try the same on SQL Server 2005:

Table 2

 

N

T1T2T3V1V2
100.50.55.30.20.2
10021.26.461.82.5
10009.38.513.5168140
1000067.479.271.31713313910
100000700794659

 

Too long!

 

Too long!

10000001055686736440

 

Too long!

 

Too long!

发现对比在某些情况下sql2000的速度要比2005的要快上很多!

结论:

没有通用的规则指导你什么时候用临时表什么时候用table变量.

将复杂逻辑的存储过程移植到sql2005的时候,要格外小心!他可能比2000的效率要慢上好几十倍的!

在你的实际测试中,请测试两个极端:销量数据和超大量数据.

无庸质疑,表变量在小数据量的情况下比临时表要好,超过一个临界值就会比临时表差,这个临界值是多少,看各人的系统的具体情况吧.

我的这个临界值总是在800,再或者1000,预计记录数超过1000的话,总是使用临时表,再在查询的临时表的键上建立索引,顺便说一句:记得增大tempdb数据空间,tempdb.mdf数据文件存放在RAID 0上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值