[英]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.