一:背景
1. 讲故事
今天和大家聊一套面试中经常被问到的高频题,对,就是 临时表 和 表变量 这俩玩意,如果有朋友在面试中回答的不好,可以尝试看下这篇能不能帮你成功迈过。
二:到底有什么区别
1. 前置思考
不管是 临时表 还是 表变量 都带了 表 这个词,既然提到了 表 ,按推理自然会落到某一个 数据库 中,如果真在一个 数据库 中,那自然就有它的存储文件 .mdf 和 .ldf,那是不是如我推理的那样呢? 查阅 MSDN 的官方文档可以发现,临时表 和 表变量 确实都会使用 tempdb 这个临时存储数据库,而且 tempdb 也有自己的 mdf,ndf,ldf 文件,截图如下:

有了这个大思想之后,接下来就可以进行验证了。
2. 如何验证都存储在 tempdb 中 ?
要想验证其实很简单,sqlserver 提供了多种方式观察。
- 查询的过程中观察 tempdb 下是否存在 xxx 表。
- 使用动态管理视图 sys.dm_db_session_space_usage 查询当前sql占用tempdb下的数据页个数。
为了让测试效果明显,我分别插入 10w 条记录观察 数据页 占用情况。
- CREATE TABLE #temp
- (
- id INT,
- content CHAR(4000) DEFAULT 'aaaaaaaaaa'
- );
- GO
- INSERT INTO #temp(id)
- SELECT TOP 100000
- ROW_NUMBER() OVER (ORDER BY o1.object_id) AS id
- FROM sys.objects AS o1,sys.objects AS o2;
- GO
- SELECT * FROM sys.dm_db_session_space_usage
- WHERE session_id=@@SPID;
复制代码
从图中的 user_objects_alloc_page_count=50456 看,当前的 insert 操作占用了 50456 个数据页。
接下来展开 tempdb 数据库以及观察到的 mdf 文件大小,都验证了存储到 tempdb 这个结论。

因为表变量的特殊性,这里我故意暂停 1min 让查询迟迟得不到结束,在这期间方便展开 tempdb,重启 sqlserver 恢复初始状态后,执行如下 sql:- DECLARE @temp TABLE
- (
- id INT,
- content CHAR(4000) DEFAULT 'aaaaaaaaaa'
- );
- INSERT INTO @temp(id)
- SELECT TOP 100000
- ROW_NUMBER() OVER (ORDER BY o1.object_id) AS id
- FROM sys.objects AS o1,sys.objects AS o2;
- SELECT * FROM sys.dm_db_session_space_usage
- WHERE session_id=@@SPID;
-
- WAITFOR DELAY '00:01:00'
复制代码
从图中可以看到 表变量 也会占用 5w+ 的数据页并且数据文件会膨胀。
3. 不同点在哪里
对底层存储有了了解之后,接下来按照重要度从高到低来了解一下区别吧。
所谓的 统计信息,就是对表数据绘制一个 直方图 来掌握数据的分布情况,sqlserver 在择取较优的执行计划时会严重依赖于这个 直方图,由于展开不了 Statistics 列,这里就从执行计划上观察,如下图所示:
选中 SELECT * FROM #temp WHERE id > 10 AND id 10 AND id |