TempDB 中表变量和局部临时表的对比
参考资料来源:
http://blogs.msdn.com/b/sqlserverstorageengine/archive/tags/tempdb/
我们都知道,tempdb是用来为应用程序和SQL Server临时储存运行的中间结果的。由用户和应用程序创建的对象叫做用户对象,由SQL
Server引擎产生的对象叫做内部对象,在这篇博文中,我们主要讨论用户对象中的临时表(#,##)和表变量。大家可能对##表(全局临时表)和#表(局部临时表)的区别比较了解,但对临时表和表变量却不是很清楚,下面我们详述两者的主要区别。
和其他变量一样,表变量是一种非常有用的程序构造。表变量的有效范围和其他程序变量的有效范围是一样的。例如,如果你在存储过程中定义了一个变量,那么它就不能在存储过程外被访问。巧合的是,临时表也是这样的。那为什么我们还要创建表变量呢?因为表变量在存储过程中可以作为输出/输入参数(此功能从SQL
Server2008开始可用)或者用来存储函数的返回结果。以下是表变量和临时表的相同和不同之处:
• 首先,表变量不一定常驻内存。在内存压力大的时候,属于表变量的页可以被放入tempdb。以下是一个例子描述表变量在tempdb中所占空间。
use tempdb
go
drop table #tv_source
go
create table #tv_source(c1 int, c2 char(8000))
go
declare @i int
select @i = 0
while (@i < 1000)
begin
insert into #tv_source values (@i, replicate ('a', 100))
select @i = @i + 1
end
DECLARE @tv_target TABLE (c11 int, c22 char(8000))
INSERT INTO @tv_target (c11, c22)
SELECT c1, c2
FROM #tv_source
-- checking the size through DMV.
-- The sizes here are in 8k pages. This shows the
allocated space
-- to user objects to be 2000 pages (1000 pages
for #tv_source and
-- 1000 pages for @tv_target
Select total_size = SUM (unallocated_extent_page_count) +
SUM (user_object_reserved_page_count) +
SUM (internal_object_reserved_page_count) +
SUM (version_store_reserved_page_count) +
SUM (mixed_extent_page_count),
SUM (unallocated_extent_page_count) as freespace_pgs,
SUM (user_object_reserved_page_count) as user_obj_pgs,
SUM (internal_object_reserved_page_count) as internal_obj_pgs,
SUM (version_store_reserved_page_count) as version_store_pgs,
SUM (mixed_extent_page_count) as mixed_extent_pgs
from sys.dm_db_file_space_usage
• 其次,如果您创建了一个表变量,它会像一个常规的DDL操作一样将元数据储存在系统目录中,以下示例说明了这一点:
declare @ttt TABLE(c111 int, c222 int)
select name from sys.columns where object_id > 100 and name
like 'c%'
结果会返回两行,包含列C111和C222。这表明如果遇到定义冲突时,把临时表改成表变量不能解决问题。
• 第三,事务处理和锁定语句。表变量不能参与事务处理和锁定,以下示例说明了这一点
-- create a source table
create table
tv_source(c1 int, c2 char(100))
go
declare @i int
select @i = 0
while (@i < 100)
begin
insert into tv_source values (@i, replicate ('a', 100))
select @i = @i + 1
end
-- using #table
create table #tv_target (c11 int, c22 char(100))
go
BEGIN TRAN
INSERT INTO #tv_target (c11, c22)
SELECT c1, c2
FROM
tv_source
--
using table variable
DECLARE @tv_target TABLE (c11 int, c22 char(100))
BEGIN TRAN
INSERT INTO @tv_target (c11, c22)
SELECT c1, c2
FROM tv_source
-- Now if I look at the locks, you will see that
only
-- #table takes locks. Here is the query that
used
-- to check the locks
select
t1.request_session_id as spid,
t1.resource_type as type,
t1.resource_database_id as dbid,
(case
resource_type
WHEN 'OBJECT' then object_name(t1.resource_associated_entity_id)
WHEN 'DATABASE' then ' '
ELSE (select object_name(object_id)
from sys.partitions
where hobt_id=resource_associated_entity_id)
END) as objname,
t1.resource_description as description,
t1.request_mode as mode,
t1.request_status as status,
t2.blocking_session_id
from sys.dm_tran_locks as t1 left outer join sys.dm_os_waiting_tasks as t2
ON t1.lock_owner_address = t2.resource_address
另一个有趣的现象是,如果回滚的事务里涉及表变量,表变量的数据不会被回滚。
Rollback
-- this
query will return 100 for table variable but 0 for #table.
SELECT COUNT(*) FROM @tv_target
• 第四,表变量上的操作不被日志文件记录。请看下面这个例子:
--
create a table variable, insert bunch of rows and update
DECLARE @tv_target TABLE (c11 int, c22 char(100))
INSERT INTO @tv_target (c11, c22)
SELECT c1, c2
FROM tv_source
-- update all the rows
update @tv_target set c22 = replicate ('b', 100)
-- look at the top 10 log records. I get no
records for this case
select top 10 operation,context, [log record fixed length], [log record length],
AllocUnitId, AllocUnitName
from fn_dblog(null, null)
where AllocUnitName like '%tv_target%'
order by [Log Record Length] Desc
-- create a local temptable
drop table #tv_target
go
create table #tv_target (c11 int, c22 char(100))
go
INSERT INTO #tv_target (c11, c22)
SELECT c1, c2
FROM tv_source
--
update all the rows
update #tv_target set c22 = replicate ('b', 100)
-- look
at the log records. Here I get 100 log records for update
select
operation,context, [log
record fixed length], [log record length], AllocUnitName
from fn_dblog(null, null)
where AllocUnitName like '%tv_target%'
order by [Log
Record Length] Desc
• 第五,表变量中不允许DDL运行,所以,如果你有一个大的行集需要经常进行查询,您可能要使用临时表并创建合适的索引。你可以在声明表变量时创建唯一约束来解决这个问题。
• 第六,表变量不维护统计数据。这意味着任何表变量数据更改都不会引起相关查询语句进行重编译。
• 最后, 涉及表变量的查询不能生成并行的查询计划,因此我们认为对于庞大的临时数据集最好使用临时表来发挥并行查询的优势。
TempDB 中表变量和局部临时表的对比的更多相关文章
- sqlserver中表变量和变量表之间区别
sqlserver中表变量和变量表之间区别
- Python决定一个变量时局部的,还是全局的,是在编译期
Python中的变量名是在编译时就解析好的,换句话说,在编译时(也就是在交互控制台输入代码是或者import文件时),Python就已经决定一个变量应该是局部变量,还是全局变量.来看下面的例子: &g ...
- vs如何新建自己工程的环境变量(局部)和 Windows系统(全局).
来源:http://blog.csdn.net/jtop0/article/details/7574139 在vs2008的Project->Property设置里经常会看到类似$ ...
- Sqlserver 实际开发中表变量的用法
在实际的开发中,我们可能遇到的问题是,在一个存储过程里面,我们可能要返回多段sql的结果集,但是最终怎么把多个结果集合成一块呢,那么这个时候临时表变量就来了 declare @tmp table ...
- vs2008如何新建自己工程的环境变量(局部)和 Windows系统(全局). .
在vs2008的Project->Property设置里经常会看到类似$(IntDir).$(OutDir).$(ProjectName) 的预定义宏.以vc2008为例,有时候我们在引用别的库 ...
- sql中表变量
今天在公司看sql优化的文章的时候,提到了表变量,做下笔记. 表变量 顺便复习下临时表.
- (八)Activiti之流程变量和局部流程变量
一.流程变量 1.1 概念 如果,当流程走到"学生请假"这个任务节点的时候,此时可以用TaskService设置流程变量,变量值包含请假人.请假时间.请假理由等信息,这些信息存在表 ...
- 在SSIS中的不同组件间使用局部临时表
Connetion的属性RetainSameConnection是个boolean值,指定是否保持相同的链接,默认值是false,表示每个component都会单独的使用connection,在com ...
- java静态变量、实例变量和局部变
实例变量又称成员变量: 1⃣️成员变量定义在类中,在整个类中都可以被访问 2⃣️成员变量随着对象的建立而建立,随对象的消失而消失,存在于对象所在的对内存中 3⃣️成员变量有默认初始值 局部变量: 1⃣ ...
随机推荐
- SWT的TreeViewer和TableViewer的交互
左边是一个TreeViewer,右边是一个TableViewer.当点击左边的treeitem的时候,右边的tableViewer要将该item的子节点信息显示出来.就像这样: 左边的treeView ...
- SVN的命令行操作
最近在进行svn二次开发,使用的是svnkit.看了很多svnkit的api,渐渐发现都是和SVN的命令行操作对应的.顺便研究一下svn的命名行操作. 1.将文件checkout到本地目录: 基本命令 ...
- HDOJ 5276 YJC tricks time multimap
multimap的使用 YJC tricks time Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/262144 K ...
- 集合中Set_List必须覆盖 hashCode()与 equals()
集合中Set_List必须覆盖 hashCode()与 equals() @Override public int hashCode() { System.out.println("==== ...
- [HDU 1427]速度计算24点(DFS暴力搜索)
主题连接: pid=1427">http://acm.hdu.edu.cn/showproblem.php?pid=1427 思路:简单的DFS.dfs(sum,next,p)表 ...
- Gulp实现服务器
Gulp实现web服务器 Gulp实现web服务器 阅读目录 一:gulp实现web服务器配置: 二:添加实时刷新(livereload)支持 回到顶部 一:gulp实现web服务器配置: 对于前端开 ...
- 【PHP】PHP5.4.0版本号ChangeLog具体解释(上)
前言 随着大量的框架使用composer和namespace,渐渐的线上环境也从之前的5.3变成了5.4或者5.5甚至5.6,随着7月份PHP7的公布,会有很多其它的公司採用新版本号. 之前好久就想写 ...
- poj 2586 Y2K Accounting Bug (贪心)
Y2K Accounting Bug Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8678 Accepted: 428 ...
- 【原创】shadowebdict开发日记:基于linux的简明英汉字典(三)
全系列目录: [原创]shadowebdict开发日记:基于linux的简明英汉字典(一) [原创]shadowebdict开发日记:基于linux的简明英汉字典(二) [原创]shadowebdic ...
- Android适应方案汇总(三)
在Android适应方案汇总(一个).(两)在.我们理解一些基本概念. 那么详细的开发,我们应该重视起来. 首先,我们需要知道.关键的事实是,这两个适配器: (1).这点在单位的使用上用dp.sp以及 ...