SQL Server 查询表值参数的短路 EXISTS 语句

Posted

技术标签:

【中文标题】SQL Server 查询表值参数的短路 EXISTS 语句【英文标题】:Short Circuit EXISTS statment in SQL Server query for Table Valued Parameters 【发布时间】:2013-01-09 14:56:48 【问题描述】:

我使用存储过程:

在我的 WHERE 子句中,我使用短路 (OR) 来加速执行,因为查询优化器知道我的大部分输入都默认为 Null。这让我的查询变得灵活而快速。

我在 WHERE 子句中添加了一个表值参数。报告的执行时间从 150 毫秒上升到 450 毫秒,从 70,000 到 200,000。

...
WHERE
    --Integer value parameters
    AND ((@hID is Null) OR (h.ID = @hID))
    AND ((@dID is Null) OR (d.ID = @dID))
    AND ((@mID is NULL) OR (m.ID = @mID))
    --New table value parameter 
    --Execute, Processing time and read's increased. 
    --No additional JOIN added.
    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))

我怎样才能短路不存在或加快这个查询?在执行查询之前,我尝试添加一个 BIT 值并检查行是否在表值参数中。我发现的唯一方法是有两个查询并在另一个上执行一个。如果我必须修改一大堆查询或将多个表值参数添加到组合中,那就不好了。

提前致谢。

编辑:

表值参数比较:

    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))

和整数参数:

    AND ((@rID) OR (r.ID = @rID))

使用 TVP 在 0 行和 Integer 参数 null 编译后显示类似的执行速度。我假设查询优化器在正确的庄园中短路,而我之前的比较是不正确的。执行计划将上述成本分为 55% 和 45%,这是可以接受的。尽管当 TVP 中有更多行时拆分不会改变,但生成报告的时间会增加,因为必须从磁盘读取更多页面。很有趣。

【问题讨论】:

你试过option ( recompile )在不缓存执行计划的情况下检查性能吗? 我尝试了 OPTION (RECOMPILE),查询时间增加了两倍。谢谢 【参考方案1】:
if exists (select * from @rIDs)
    begin
    .... -- query with TVP
    end
else
    begin
    .... -- query without TVP
    end

这允许为每个查询单独执行计划。

【讨论】:

我在我的问题中提到了这种方法,但我有大量的变量和查询需要考虑。如果找不到适合我的查询的解决方案,我可能不得不使用这种方法。 你可以试试option (recompile),它会强制每次查询执行都进行编译。然后将使用实际行数估计查询计划。考虑到您问题中的运行时间,这当然可以得到回报,因为典型的重新编译只需 20 毫秒。 感谢 Andomar,感谢对 option(recompile) 选项的解释【参考方案2】:

看起来您正在使用表变量。如果您使用临时表并索引您用于条件的列(在您的示例中为 r),您将避免表扫描。然而,这使它成为一个多步骤的过程,但它们的回报可能是巨大的。

为了更具体地解决您的问题,您可以将示例的最后一行更改为 AND 存在(从@rIDs 中选择 r,其中 r = r.ID 而不是 r 为 NULL)

如果您可以发布执行计划,我可以给您一个更好的答案。点击Display Estimated Execution Plan,右击执行计划,选择Save Execution Plan As...

【讨论】:

我会说 the payoff *can* be huge 而不是一揽子声明暗示这是应该始终这样做的方式。您发布的语法也不正确:AND EXISTS r.ID IN ...? 嗨,约翰,我可以在表中添加一个索引,我的问题是如果 TVP 有零行,那么我希望索引扫描是无关紧要的。我也尝试了 EXISTS r.ID IN 但它抱怨语法,这是 2012 年的功能吗? 对你和亚伦都很抱歉。我在上面编辑了我的答案。我的复制粘贴出错了。您有机会查看执行计划吗?【参考方案3】:

您可以尝试在要查询的表(左侧)和 TVP 之间进行 LEFT JOIN。

【讨论】:

以上是关于SQL Server 查询表值参数的短路 EXISTS 语句的主要内容,如果未能解决你的问题,请参考以下文章

如果不需要,SQL Server 是不是足够聪明,不会执行昂贵的查询? (短路)

在这种特定情况下,SQL Server 会始终短路吗?

SQL Server - 按可变数量的参数过滤查询

对于 CONTAINS 全文谓词,SQL Server 2008 中的逻辑短路似乎失败

SQL-Server存储过程中的参数问题!

几个SQL Server的查询题!