执行计划 - 由于 ISNULL 而不使用索引查找

dex*_*xon 2 sql-server performance-tuning

我有一个我想要改进的程序,它使用这个 where 子句:

WHERE   p.PlatformId = ISNULL(@PlatformId, p.PlatformId)
and p.PayeeStsId     = 1
and p.PlatformPayeeId   = ISNULL(@platformPayeeId, p.PlatformPayeeId)
and pba.PayeeBankStsId=1
and a.Gcid = ISNULL(@Gcid, a.Gcid)
Run Code Online (Sandbox Code Playgroud)

ISNULL给我使用索引带来了问题,我怎样才能避免使用这种格式ISNULL

p.PlatformId = ISNULL(@PlatformAccountId, p.PlatformId)
Run Code Online (Sandbox Code Playgroud)

这种格式导致执行计划进行索引扫描。

Eri*_*ing 5

门#1

OPTION(RECOMPILE)您可以在查询末尾添加提示。这里的缺点是 SQL Server 每次都必须为其编译一个计划,并且计划缓存中不会有太多线索(如果启用了查询存储,这没什么大不了的)。

好处是,每次运行时,优化器都会使用文字值替换参数或变量占位符来有效地执行查询。这将允许在索引合适时进行查找。

门#2

您可以使用参数化动态 SQL 为任何非 NULL 参数生成 where 子句。这是一个基于您提供的有限信息的松散示例。

DECLARE
    @s nvarchar(MAX) = N'',
    @parameters nvarchar(MAX) = N'@PlatformId integer, @platformPayeeId integer, @Gcid integer';

SELECT
    @s += N'
SELECT
    columns
/*Put the name of your stored procedure in a comment so people know where it comes from*/
FROM dbo.YourTable AS p
JOIN dbo.YourOtherTable AS pba
  ON p.Id = pba.Id
JOIN dbo.YourOtherOtherTable AS a
  ON p.Id = a.Id
WHERE p.PayeeStsId = 1
AND   pba.PayeeBankStsId = 1';

IF @PlatformId IS NOT NULL
BEGIN
    SELECT
        @s += N'
AND   p.PlatformId = @PlatformId'
END;

IF @platformPayeeId IS NOT NULL
BEGIN
    SELECT
        @s += N'
AND   p.PlatformPayeeId = @platformPayeeId'
END;

IF @Gcid IS NOT NULL
BEGIN
    SELECT
        @s += N'
AND   a.Gcid = @Gcid'
END;

EXEC sys.sp_executesql
    @s,
    @parameters,
    @PlatformId,
    @platformPayeeId,
    @Gcid;
Run Code Online (Sandbox Code Playgroud)

当然,您需要根据您的具体情况进行调整,但这应该会让您朝着正确的方向前进。