繁体   English   中英

参数导致SQL Server中的表扫描

[英]Parameter cause a table scan in SQL Server

我有两个表a,b,主键是它们的索引。

需求:

如果@filter为空,则选择a,b的所有记录,否则按任何特定分隔符拆分@filter ,查找b.PKey在过滤器中的记录。

目前的实施:

declare @filter nvarchar(max)= ''

SELECT * 
FROM a
JOIN b ON a.PKey = b.aPKey
       AND (@filter = '' OR b.PKey IN (SELECT item FROM splitFunction(@filter))

我发现最后一个语句and (@filter = '' or b.PKey in (select item from splitFunction(@filter))将始终在表b上进行表扫描,只有当我删除@filter='' ,它才会改变索引寻求。

有没有办法可以实现我的要求并且不会损害性能?

特别针对这种情况,你也可以试试这个:

DECLARE @filter nvarchar(max)= ''

IF @filter = ''
BEGIN
    SELECT * 
    FROM a
    JOIN b ON a.PKey = b.aPKey
END
ELSE 
BEGIN
    SELECT * 
    FROM a
    JOIN b ON a.PKey = b.aPKey
    WHERE b.PKey IN (SELECT item FROM splitFunction(@filter))
END

对于常量,优化程序可以根据给定值的统计信息计算出最佳计划。

当您使用变量时,您将强制参数化,并且该计划将被设计为可以重复使用各种值。 所以Optimizer使用扫描而不是搜索。 要解决此问题,请在查询中停止使用局部变量,并将其用作存储过程中的参数

create procedure p1
@filter = ''
as
begin
SELECT * 
FROM a
JOIN b ON a.PKey = b.aPKey
       AND (@filter = '' OR b.PKey IN (SELECT item FROM splitFunction(@filter))
option (recompile)
end

这将为您提供正确的计划,就像我已将本地变量转换为参数的存储过程一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM