SQL Server 临时表和表变量系列之踢馆篇

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: # 摘要 在面对SQL Server选择使用临时表还是表变量作为数据暂存问题时,有一个非常重要的选择标准便是性能,两者对于查询语句和DML性能表现到底如何呢?我相信,很多人的认识是片面的,或者是错误的。这里以一篇引用率很高的文章来作为反面教材来纠正那些片面和错误的认识,我暂且称之为“踢馆”。 # 背景 在研究临时表和表变量该如何选择的时候,一篇文章叫着[SQL Server Temp Tab

摘要

在面对SQL Server选择使用临时表还是表变量作为数据暂存问题时,有一个非常重要的选择标准便是性能,两者对于查询语句和DML性能表现到底如何呢?我相信,很多人的认识是片面的,或者是错误的。这里以一篇引用率很高的文章来作为反面教材来纠正那些片面和错误的认识,我暂且称之为“踢馆”。

背景

在研究临时表和表变量该如何选择的时候,一篇文章叫着SQL Server Temp Table vs Table Variable Performance Testing文章引用率是非常高的。通读全文,作者褒“临时表”贬“表变量”的语调跃然纸上,虽然原作者也有唯物辩证的思维去看待这个问题。但,综合起来原作者认为临时表性能好于表变量。事实上真的是这样子的吗?这篇文章会一探究竟。

分析

首先,原作者的测试环境的搭建存在漏洞,非常不严谨。体现在作者为临时表在col2上创建了非聚集索引,而表变量上的col2上没有定义非聚集索引。根据生物学对比试验方法论,实验组与对比组只允许有一个变化的影响因素,但是原作者这里引入了两个变化因素:第一是临时表和表变量;第二个变化因素是临时表具有索引,而表变量没有索引。这可能是因为作者认为表变量不能够创建索引,证据在原作者的这句话“However, when we query rows using the indexed column of the temporary table, which is not indexed in the table variable since this is not available for table variables, we see a really big increase in performance across all measures for the temporary table. ”,但实际上表变量同样是可以创建索引的,只不过必须是在定义表变量的同时创建索引,定义结束后,不支持对表变量的任何修改。详情可以参见文章SQL Server 临时表和表变量系列之认知误区篇。由于作者的这个认识误区,导致了整个测试结果不严谨,结论不够准确,给了读者踢馆的机会。
原作者对临时表创建的两个索引:

-- Create index logic
CREATE NONCLUSTERED INDEX [IX_temptable] ON #temptable ([col2] ASC)
CREATE NONCLUSTERED INDEX [IX_bigtemptable] ON #bigtemptable ([col2] ASC)

测试

毛爷爷说:“实践出真知,没有调查就没有发言权。”,我们按照原作者的思路,纠正作者测试环境搭建的疏漏,然后再来测试INSERT、SELECT、UPDATE和DELETE操作性能。为两个表变量在col2上创建索引,定义表变量时,添加了语句index IX_col2(col2 ASC)。代码如下:

-- Table creation logic
CREATE TABLE #temptable ([col1] [int] NOT NULL primary key,[col2] [int] NULL,
[col3] [int] NULL,[col4] [varchar](50) NULL)
DECLARE @tablevariable TABLE ([col1] [int] NOT NULL primary key,[col2] [int] NULL,
[col3] [int] NULL,[col4] [varchar](50) NULL, index IX_col2(col2 ASC))
CREATE TABLE #bigtemptable ([col1] [int] NOT NULL primary key,[col2] [int] NULL,
[col3] [int] NULL,[col4] [varchar](50) NULL)
DECLARE @bigtablevariable TABLE ([col1] [int] NOT NULL primary key,[col2] [int] NULL,
[col3] [int] NULL,[col4] [varchar](50) NULL, index IX_col2(col2 ASC))
-- Create index logic
CREATE NONCLUSTERED INDEX [IX_temptable] ON #temptable ([col2] ASC)
CREATE NONCLUSTERED INDEX [IX_bigtemptable] ON #bigtemptable ([col2] ASC)

保持其他的地方原封不动,在一个连接中,执行所有的语句。

INSERT语句性能对比

原作者对INSERT语句测试结果截图如下:
07.png
原作者得出的结论:“This can probably be attributed to the fact that the temporary table has an extra index on the table that needs to be updated as well.”
这个结论不攻自破了,由于作者没有对表变量创建索引,所以会认为临时表的索引导致了插入效率比表变量低。来看看纠正了测试环境的错误后的测试结果:
08.png
从这个测试结果来看,表变量有一条插入语句比临时表更慢;另一条插入语句两者性能相当。

SELECT语句性能对比

原作者对SELECT语句测试结果的截图如下(我用红色长方形框标记了对比之处):
01.png
还是由于原作者对表变量没有创建索引,导致通过col2条件查询表变量的时候,得出的测试结论不正确:使用临时表的时间消耗为1毫秒,使用表变量时间消耗为99毫秒,临时表效率更高。我的测试结果截图如下:
02.png
从我的测试接过来看,使用临时表的时间消耗为626毫秒,而使用表变量的时间消耗仅为100毫秒,表变量效率更高,这个和原作者的结论恰好相反。

UPDATE语句性能对比

UPDATE语句由于原作者截图中无法看到执行时间消耗。所以,我们采用CPU和Reads来对比:原测试使用表变量在CPU和IO读两个方面相对于临时表性能消耗更高,效率更低。
03.png
而我们的测试结果恰好相反,两者在CPU方面相当,均为0,而IO读取方面,表变量性能更高,与原作者结论恰好相反。得出这个测试结果的原因还是因为为表变量创建了索引。
04.png

DELETE语句性能对比

原作者对DELETE语句测试的截图如下。由截图来看,表变量在CPU消耗,IO读取和执行时间消耗三个层面,性能消耗相对于临时表都更高,效率都更低。
05.png
而我们的测试结果截图如下:临时表CPU消耗更严重,IO读表变量更高,执行时间表变量稍微高一点,1毫秒的差异几乎可以忽略不计。
06.png

总结

之所谓“差之毫厘谬以千里”,由于原作者忽略了对表变量定义索引,亦或者是不知道为表变量创建索引,导致整个性能对比测试不严谨,测试结果和事实大相径庭,给了我们踢馆的机会。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
3天前
|
SQL 存储 数据库连接
LabVIEW与SQL Server 2919 Express通讯
LabVIEW与SQL Server 2919 Express通讯
|
4天前
|
SQL Windows
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
12 4
|
5天前
|
SQL 数据可视化 Oracle
这篇文章教会你:从 SQL Server 移植到 DM(上)
这篇文章教会你:从 SQL Server 移植到 DM(上)
|
5天前
|
SQL 关系型数据库 数据库
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
|
5天前
|
SQL 存储 网络协议
SQL Server详细使用教程
SQL Server详细使用教程
26 2
|
5天前
|
SQL 存储 数据库连接
C#SQL Server数据库基本操作(增、删、改、查)
C#SQL Server数据库基本操作(增、删、改、查)
7 0
|
5天前
|
SQL 存储 小程序
数据库数据恢复—Sql Server数据库文件丢失的数据恢复案例
数据库数据恢复环境: 5块硬盘组建一组RAID5阵列,划分LUN供windows系统服务器使用。windows系统服务器内运行了Sql Server数据库,存储空间在操作系统层面划分了三个逻辑分区。 数据库故障: 数据库文件丢失,主要涉及3个数据库,数千张表。数据库文件丢失原因未知,不能确定丢失的数据库文件的存放位置。数据库文件丢失后,服务器仍处于开机状态,所幸未写入大量数据。
数据库数据恢复—Sql Server数据库文件丢失的数据恢复案例
|
6天前
|
SQL 存储 关系型数据库
SQL Server详细使用教程及常见问题解决
SQL Server详细使用教程及常见问题解决
|
7天前
|
SQL 安全 数据库
SQL Server 备份和还原
SQL Server 备份和还原
|
7天前
|
SQL 存储 安全
SQL Server 权限管理
SQL Server 权限管理