惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
J
Java Code Geeks
雷峰网
雷峰网
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
V
Vulnerabilities – Threatpost
S
Securelist
The Hacker News
The Hacker News
The Register - Security
The Register - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
G
Google Developers Blog
Hugging Face - Blog
Hugging Face - Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
AI
AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Schneier on Security
Schneier on Security
N
Netflix TechBlog - Medium
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
Hacker News - Newest:
Hacker News - Newest: "LLM"
H
Hacker News: Front Page
博客园 - 司徒正美
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
B
Blog
Microsoft Azure Blog
Microsoft Azure Blog
大猫的无限游戏
大猫的无限游戏
Security Latest
Security Latest
Engineering at Meta
Engineering at Meta
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Threat Research - Cisco Blogs
U
Unit 42
V
V2EX
V2EX - 技术
V2EX - 技术
L
LINUX DO - 最新话题
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
Recorded Future
Recorded Future
P
Privacy & Cybersecurity Law Blog
美团技术团队
小众软件
小众软件
F
Fortinet All Blogs

博客园 - 在北京的湖南人

C#trim不掉空格的原因 - 在北京的湖南人 - 博客园 vss2005 只获取到文件夹获取不到文件的解决 关于asp.net session机制的疑惑以及猜想 一段关于浏览器兼容的事件定位代码,经过测试! 收集关于scrollTop信息 数据库中null字段在逻辑层的判断的两种办法 - 在北京的湖南人 - 博客园 sql server 2005 新分页存储过程 sql 优化之关于null 和数据类型 js trim函数 复制粘贴都出错,还有什么错不能出的? sql 优化实战 从 35秒到0秒 又从0秒到25秒 asp.net上传时出现的问题:"对路径的访问被拒绝" gridview超链接列带多个参数 访问 IIS 元数据库失败 sql server clr 集成系列之四 创建一个clr的表值函数---实用的Split函数 sql server 2005 clr 集成 之三 关于context connetion sql server clr 集成系列之二 简单的sql 函数 Sql server 2005 Clr集成系列开篇 为什么微软要集成clr 到sql server? return语句写错地方导致数据库表长时间被锁
Table变量和临时表区别
在北京的湖南人 · 2007-06-07 · via 博客园 - 在北京的湖南人

区别一:

<PRE lang=sql>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 @</PRE>

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

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

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

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

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

然后创建存储过程: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

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

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

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

(*) 是存储过程参数.

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

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

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

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

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

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

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

CREARE 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

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

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
      WHEREre V.n
=NUM.n)
GO<

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

Table 1, using SQL Server 2000, time in ms

Records
T1 T2 T3 V1 V2
10 0.7 1 13.5 0.6 0.8
100 1.2 1.7 14.2 1.2 1.3
1000 7.1 5.5 27 7 5.3
10000 72 57 82 71 48
100000 883 480 580 840 510
1000000 45056 6090 15220 20240 12010

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

Table 2

N
T1 T2 T3 V1 V2
10 0.5 0.5 5.3 0.2 0.2
100 2 1.2 6.4 61.8 2.5
1000 9.3 8.5 13.5 168 140
10000 67.4 79.2 71.3 17133 13910
100000 700 794 659

Too long!

Too long!

1000000 10556 8673 6440

Too long!

Too long!

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

结论:
没有通用的规则指导你什么时候用临时表什么时候用table变量.
将复杂逻辑的存储过程移植到sql2005的时候,要格外小心!他可能比2000的效率要慢上好几十倍的!
在你的实际测试中,请测试两个极端:销量数据和超大量数据.

此文章翻译自codeproject:http://www.codeproject.com/cs/database/SQP_performance.asp