首页 > 数据库

Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance

时间:2009-04-23 12:54:28  作者:武树伟  我要投稿
Linux初探欢迎您的投稿,投放方法请点击这里查看,我们会定期赠送精美小礼品给优秀的投稿作者。海纳百川 取则行远!LinuxGoo欢迎您的到来。
Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance September 13th, 2007 Original http://www.sqlsolutions.com/articles/ar......

Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance

September 13th, 2007

Original http://www.sqlsolutions.com/articles/articles/Temporary_Tables_vs._Table_Variables_and_Their_Effect_on_SQL_Server_Performance.htm

There are 3 major theoretical differences between temporary tables:

create table #T (...)



and table-variables



declare @T table (...)

The first one is that transaction logs are not recorded for the table-variables. Hence, they are out of scope of the transaction mechanism, as is clearly visible from this example:

create table #T (s varchar(128))

declare @T table (s varchar(128))

insert into #T select 'old value #'

insert into @T select 'old value @'

begin transaction

  update #T set s='new value #'

  update @T set s='new value @'

rollback transaction

select * from #T

select * from @T



s              

--------------- 

old value #



s                 

--------------- 

new value @

After declaring our temporary table #T and our table-variable @T, we assign each one with the same 'old value' string. Then, we begin a transaction that updates their contents. At this point, both will now contain the same 'new value' string. But when we rollback the transaction, as you can see, the table-variable @T retained its value instead of reverting back to the 'old value' string. This happened because, even though the table-variable was updated within the transaction, it is not a part of the transaction itself.

The second major difference is that any procedure with a temporary table cannot be pre-compiled, while an execution plan of procedures with table-variables can be statically compiled in advance. Pre-compiling a script gives a major advantage to its speed of execution. This advantage can be dramatic for long procedures, where recompilation can be too pricy.

Finally, table-variables exist only in the same scope as variables. Contrary to the temporary tables, they are not visible in inner stored procedures and in exec(string) statements. Also, they cannot be used in insert/exec statement.

But let's compare both in terms of performance.

At first, we prepare a test table with 1 million records:

create table NUM (n int primary key, s varchar(128))

GO

set nocount on

declare @n int

set @n=1000000

while @n>0 begin 

  insert into NUM 

    select @n,'Value: ' convert(varchar,@n)

  set @n=@n-1

  end

GO

Now we prepare our test procedure T1:

create procedure T1

  @total int

as

  create table #T (n int, s varchar(128))

  insert into #T select n,s from NUM 

    where n%100>0 and n<=@total

  declare @res varchar(128)

  select @res=max(s) from NUM

    where n<=@total and

      not exists(select * from #T 

      where #T.n=NUM.n)

GO

Called with a parameter, which we will vary from 10, 100, 1000, 10'000, 100'000 up to 1'000'000, it copies the given number of records into a temporary table (with some exceptions, it skips records where n is divisible by 100), and then finds a max(s) of such missing records. Of course, the more records we give, the longer the execution is.

To measure the execution time precisely, I use the code:

declare @t1 datetime, @n int

set @t1=getdate()

set @n=100-- (**)

while @n>0 begin

  exec T1 1000 -- (*)

  set @n=@n-1 end

select datediff(ms,@t1,getdate())

GO

(*) is a parameter to our procedure, it is varied from 10 to 1'000'000
(**) if an execution time is too short, I repeat the same loop 10 or 100 times.
I run the code several times to get a result of a 'warm' execution.

The results can be found in Table 1 (see below).

Now let's try to improve our stored procedure by adding a primary key to the temporary table:

create procedure T2

  @total int

as

  create table #T (n int primary key, s varchar(128))

  insert into #T select n,s from NUM 

    where n%100>0 and n<=@total

  declare @res varchar(128)

  select @res=max(s) from NUM

    where n<=@total and

      not exists(select * from #T 

      where #T.n=NUM.n)

GO

Then, lets create a third one. With a clustered index, it works much better. But let's create the index AFTER we insert data into the temporary table - usually, it is better:

create procedure T3

  @total int

as

  create table #T (n int, s varchar(128))

  insert into #T select n,s from NUM 

    where n%100>0 and n<=@total

  create clustered index Tind on #T (n)

  declare @res varchar(128)

  select @res=max(s) from NUM

    where n<=@total and

      not exists(select * from #T 

      where #T.n=NUM.n)

GO

Surprise! It not only takes longer for the big amounts of data; merely adding 10 records take an additional 13 milliseconds. The problem is that 'create index' statements force SQL server to recompile stored procedures, and slows down the execution significantly.

Now let's try the same using table-variables:

create procedure V1

  @total int

as

  declare @V table (n int, s varchar(128))

  insert into @V select n,s from NUM 

    where n%100>0 and n<=@total

  declare @res varchar(128)

  select @res=max(s) from NUM

    where n<=@total and

      not exists(select * from @V V 

      where V.n=NUM.n)

GO

To our surprise, this version is not significantly faster than the version with the temporary table. This is a result of a special optimization SQL server has for the create table #T statements in the very beginning of a stored procedure. For the whole range of values, V1 works better or the same as T1.

Now let's try the same with a primary key:

create procedure V2

  @total int

as

  declare @V table (n int primary key, s varchar(128))

  insert into @V select n,s from NUM 

    where n%100>0 and n<=@total

  declare @res varchar(128)

  select @res=max(s) from NUM

    where n<=@total and

      not exists(select * from @V V 

      where V.n=NUM.n)

GO

The result is much better, but T2 outruns this version.

如果您需转载 Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance,请注明来自LinuxGoo.com,其版权归原作者所有。请广大网友留言时遵纪守法,使用文明用语。如果您在应用中有什么问题,请在下面留言,我们会尽快解答。
来顶一下
近回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
相关文章
栏目热门