SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文:SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?前言 上一篇我们讲完SQL动态查询,本节我们继续来讲解SQL动态查询中存在的问题。
原文: SQL Server-聚焦WHERE Column = @Param OR @Param IS NULL有问题?

前言

上一篇我们讲完SQL动态查询,本节我们继续来讲解SQL动态查询中存在的问题。

SQL动态查询条件筛选过滤

当我们创建存储过程调用存储过程时,若筛选条件有值则过滤,没有值则返回所行记录,类似如下查询:

WHERE (SomeColumn=@col OR @col IS NULL)

这样查询会存在什么问题呢?性能会不会有问题呢,这个是我们本节需要深入探讨的问题。

接下来我们创建如下测试表并插入测试数据,如下:

CREATE TABLE Test
    (
      SomeCol1 INT NOT NULL ,
      Somecol2 INT NOT NULL
    )
 
INSERT  Test
        SELECT  number ,
                low
        FROM    master..spt_values
        WHERE   TYPE = 'p'
 
 
CREATE INDEX ix_col2 ON Test(Somecol2)
GO

对于动态SQL条件筛选过滤我们利用WHERE 1 = 1来拼接。接下来我们使用一般SQL语句和动态查询并比较其IO,如下:

SET STATISTICS IO ON
GO
 
DECLARE @col INT
SELECT @col = 1
 
SELECT SomeCol2 
FROM Test
WHERE 1 =1
AND  (SomeCol2=@col OR @col IS NULL)
 
GO
 
DECLARE @col INT
SELECT @col = 1
 
DECLARE @SQL NVARCHAR(4000)
    SET @SQL = 'SELECT SomeCol2 
                FROM Test
                WHERE 1 =1'
 
IF @col IS NOT NULL 
    SET @SQL = @SQL + ' AND SomeCol2=@InnerParamcol '
    
EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col
 
SET STATISTICS IO OFF
GO

img_eba1fc8c4edb57bda6f0a87757454d46.png

img_43b3b15c5a1715580ee463e9ea7995a6.png
我们能够看到动态SQL查询逻辑读取只读取2次,而另外一般SQL语句查询逻辑读取7次,同时我们看到SQL动态查询计划执行的是索引查找,而一般SQL语句则是索引扫描。

看来执行一般SQL语句不会走索引查找,将导致性能问题,在开头我们就讲过筛选条件有值则过滤,无值则查询所有数据,那么我们完全可以借助ISNULL来查询,下面我们用ISNULL来改变一般语句筛选条件,看看是否会走索引查找呢?


SET STATISTICS IO ON
GO
 
DECLARE @col INT
SELECT @col = 1
 
SELECT SomeCol2
FROM dbo.Test
WHERE 1 = 1
AND  SomeCol2 = ISNULL(@col,SomeCol2)

img_028d7b428d892875c7c63af72a8b4875.png
img_b26186776597ffd87d7225ee8b4bdb23.png

我们看到结果依然是走索引扫描,没有任何改变。是不是就没有解决之道了呢?我们来改变一般SQL语句查询方式,如下:

DECLARE @col INT
SELECT @col = 1

IF @Col IS NULL
    SELECT  SomeCol2
    FROM    Test
    WHERE   1 = 1
ELSE
    SELECT  SomeCol2
    FROM    dbo.Test
    WHERE   1 = 1
            AND SomeCol2 = @col

GO

如上只能是勉勉强强解决了问题,因为只是针对一个参数,如果有多个参数要进行IF...ELSE..,那可就傻逼了。从本质上解决这个问题我们需要利用可选项重新编译。如下:


SET STATISTICS IO ON
GO
 
DECLARE @col INT
SELECT @col = 1
 
SELECT SomeCol2 
FROM dbo.Test
WHERE 1 =1
AND  (SomeCol2 = @col OR @col IS NULL)
OPTION(RECOMPILE)
 
 
GO
 
DECLARE @col INT
SELECT @col = 1
 
DECLARE @SQL NVARCHAR(4000)
    SET @SQL = 'SELECT SomeCol2 
                FROM dbo.Test
                WHERE 1 =1'
 
IF @col IS NOT NULL 
    SET @SQL = @SQL + ' AND SomeCol2 = @InnerParamcol '
    
    
    
EXEC sp_executesql @SQL,N'@InnerParamcol INT',@col
 
SET STATISTICS IO OFF
GO

img_3357bebce196419170bc295c9f1a979d.png

img_e1d76cb97ec9cb024b3bfb5e11d842bd.png

总结

当利用条件筛选过滤数据时,如果条件有值则过滤,否则返回所有行记录。如果执行一般SQL语句和动态SQL,那么动态SQL会走索引查找,而一般SQL语句将导致索引扫描,此时需要加上OPTION(RECOMPILE)才走索引查找。

相关实践学习
使用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
目录
相关文章
|
1天前
|
关系型数据库 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)")
|
2月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
65 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天】
47 6
|
2月前
|
SQL
SQL NOT NULL 约束
【7月更文挑战第18天】SQL NOT NULL 约束。
38 6
|
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
206 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) 对于大文本更合适,但可能影响性能。 - 选择取决于数据长度预期和业务需求。
141 1
|
2月前
|
SQL
SQL NOT NULL 约束
【7月更文挑战第16天】SQL NOT NULL 约束。
31 3
|
2月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
157 3
|
2月前
|
SQL 存储 安全
数据库数据恢复—SQL Server数据库出现逻辑错误的数据恢复案例
SQL Server数据库数据恢复环境: 某品牌服务器存储中有两组raid5磁盘阵列。操作系统层面跑着SQL Server数据库,SQL Server数据库存放在D盘分区中。 SQL Server数据库故障: 存放SQL Server数据库的D盘分区容量不足,管理员在E盘中生成了一个.ndf的文件并且将数据库路径指向E盘继续使用。数据库继续运行一段时间后出现故障并报错,连接失效,SqlServer数据库无法附加查询。管理员多次尝试恢复数据库数据但是没有成功。