SQL Server使用变量和参数以及语句执行时执行计划的差异

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介: T-SQL语句之间传输数据有以下一些途径: 1)本地变量 2)存储过程中的参数 3)应用程序变量 4)参数标记 上面4种变量中,比较常用的是本地变量和存储过程中的参数。 本地变量指在查询前declare参数,并且set设值之后,在查询语句中直接使用声明的参数,而不是直接使用其值。

T-SQL语句之间传输数据有以下一些途径:
1)本地变量
2)存储过程中的参数
3)应用程序变量
4)参数标记
上面4种变量中,比较常用的是本地变量和存储过程中的参数。

本地变量指在查询前declare参数,并且set设值之后,在查询语句中直接使用声明的参数,而不是直接使用其值。

存储过程中的参数有两种,一种是定义在存储过程里面,类似上面的本地变量,一种是定义在存储过程外面。这两种参数,都是在执行存储过程时,将参数值传入进去。不过两种定义方法各有优缺点,下一章将进行深入探讨。

应用程序变量主要指编程语言C,C++,Basic和Java等,它们都有自己的一套变量来存储值。应用程序一般通过数据库的API把T-SQL语句返回的值存储到自己的变量中,然后再使用这些值。

参数标记是放置在 T-SQL 语句中的输入表达式位置的一个问号 (?)。参数标记绑定了应用程序变量,似的应用程序变量中的数据可以用作T-SQL语句中的输入。参数标记还允许存储过程输出参数和返回代码绑定到应用程序变量。

本专题主要介绍本地变量和存储过程中的参数的定义,使用以及语句执行时执行计划的差异。

注: 下面每种情况执行之前都执行DBCC FREEPROCCACHE清除了缓存,生产环境避免执行该语句。

不使用变量和参数

直接在SSMS中赋值,SQL Server在编译时知道具体的值,给出的执行计划很准确。
SELECT p.LastName, p.FirstName, ph.PhoneNumber
FROM Person.Person AS p
JOIN Person.PersonPhone AS ph ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE 'Man%';
screenshot.png
开启SQL Server Profiler抓取SP:CacheHit和SP:CacheMiss事件,可以发现where条件换个数据后,SQL Server会根据当前的值重新生成执行计划。
screenshot.png
screenshot.png

使用本地变量

首先我们来看看本地变量的定义及使用方法。
/* Also allowed:
DECLARE @find varchar(30) = 'Man%';
*/
DECLARE @find varchar(30);
SET @find = 'Man%';
SELECT p.LastName, p.FirstName, ph.PhoneNumber
FROM Person.Person AS p
JOIN Person.PersonPhone AS ph ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE @find;
使用本地变量,SQL Server在执行语句时,根据变量的预估值进行编译,给出的执行计划比较准确。
screenshot.png
抓取SQL Server Profiler,会发现使用本地变量每次执行都会重新编译,生成新的执行计划。
screenshot.png
screenshot.png

将变量定义在存储过程里面

示例:
--local variable
create procedure sniff(@find varchar(30)) as
DECLARE @findIn varchar(30);
set @findIn=@find
SELECT p.LastName, p.FirstName, ph.PhoneNumber
FROM Person.Person AS p
JOIN Person.PersonPhone AS ph ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE @findIn;
go
与本地变量一样,它的值在存储过程语句执行过程中得到,SQL Server在运行时不知道变量的值,会根据一个预估值进行编译,给出一个折中的执行计划。
exec sniff 'Man%';
screenshot.png
exec sniff 'U%';
screenshot.png

将变量定义在存储过程外面

示例:
create procedure sniff2(@find varchar(30)) as
SELECT p.LastName, p.FirstName, ph.PhoneNumber
FROM Person.Person AS p
JOIN Person.PersonPhone AS ph ON p.BusinessEntityID = ph.BusinessEntityID
WHERE LastName LIKE @find;
go
当调用存储过程时,必须要给他带入值。第一次运行存储过程时,SQL Server根据带入的变量值进行编译,给出准确的执行计划。以后再次调用存储过程,SQL Server会重用第一次的执行计划,不会进行重编译,以达到较高的效率,这是存储过程的一大优势。
exec sniff2 'Man%';
screenshot.png
screenshot.png
exec sniff2 'U%';
screenshot.png
screenshot.png

不少客户在SQL语句中使用本地变量,会出现同一语句有时快有时慢的情况,从上面的测试应该可以得到答案了。使用存储过程,最大的好处就是可以重用执行计划,大大提高执行效率,但是这一优势同时也是存储过程的最大劣势,首次编译的执行计划如果不适用于新的参数值,有可能会让语句执行时间反很多倍,这就是著名的parameter sniffing,下一章我们将继续深入探讨。

相关实践学习
使用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
目录
相关文章
|
20天前
|
SQL 测试技术 数据处理
|
20天前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
92 0
|
2月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
63 13
|
2月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
|
2月前
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
44 6
|
2月前
|
SQL 分布式计算 MaxCompute
SQL开发问题之对于ODPS中的UNION操作,执行计划的问题如何解决
SQL开发问题之对于ODPS中的UNION操作,执行计划的问题如何解决
|
2月前
|
SQL 运维 分布式计算
DataWorks产品使用合集之ODPPS中如何使用SQL查询从表中获取值并将其赋值给临时变量以供后续使用
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
|
1月前
|
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
176 0
|
2月前
|
存储 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) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
107 1
|
2月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
138 3