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

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 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
目录
相关文章
|
5月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
7月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
182 13
|
7月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
109 9
|
7月前
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
93 6
|
7月前
|
SQL 运维 分布式计算
DataWorks产品使用合集之ODPPS中如何使用SQL查询从表中获取值并将其赋值给临时变量以供后续使用
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
|
7月前
|
存储 SQL C++
对比 SQL Server中的VARCHAR(max) 与VARCHAR(n) 数据类型
【7月更文挑战7天】SQL Server 中的 VARCHAR(max) vs VARCHAR(n): - VARCHAR(n) 存储最多 n 个字符(1-8000),适合短文本。 - VARCHAR(max) 可存储约 21 亿个字符,适合大量文本。 - VARCHAR(n) 在处理小数据时性能更好,空间固定。 - VARCHAR(max) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
588 1
|
7月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
553 3
|
6月前
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
604 0
|
7月前
|
SQL 监控 数据库
SQL Server 查询超时问题排查
【7月更文挑战第8天】排查 SQL Server 查询超时涉及五个主要方面:检查复杂查询、评估服务器性能、审视配置参数、更新统计信息和分析执行计划。关注点包括查询的结构(如连接、子查询和索引),服务器资源(CPU、内存、网络延迟),连接和内存设置,以及统计信息的时效性。通过这些步骤可定位并解决性能瓶颈。
189 0
|
7月前
|
SQL 存储 Oracle
TDengine 3.3.2.0 发布:新增 UDT 及 Oracle、SQL Server 数据接入
**TDengine 3.3.2.0 发布摘要** - 开源与企业版均强化性能,提升WebSocket、stmt模式写入与查询效率,解决死锁,增强列显示。 - taos-explorer支持geometry和varbinary类型。 - 企业版引入UDT,允许自定义数据转换。 - 新增Oracle和SQL Server数据接入。 - 数据同步优化,支持压缩,提升元数据同步速度,错误信息细化,支持表名修改。 - 扩展跨平台支持,包括麒麟、Euler、Anolis OS等。
169 0

热门文章

最新文章