Sql server SQL Server查询表值参数时存在短路

Sql server SQL Server查询表值参数时存在短路,sql-server,tsql,query-optimization,where-clause,table-valued-parameters,Sql Server,Tsql,Query Optimization,Where Clause,Table Valued Parameters,我使用存储过程: 在我的WHERE子句中,我使用短路(OR)来加速执行,因为查询优化程序知道我的大多数输入默认为Null。这使我的查询变得灵活和快速 我在WHERE子句中添加了一个表值参数。报告的执行时间从150ms增加到450ms,从70000增加到200000 ... WHERE --Integer value parameters AND ((@hID is Null) OR (h.ID = @hID)) AND ((@dID is Null) OR (d.ID =

我使用存储过程:

在我的WHERE子句中,我使用短路(OR)来加速执行,因为查询优化程序知道我的大多数输入默认为Null。这使我的查询变得灵活和快速

我在WHERE子句中添加了一个表值参数。报告的执行时间从150ms增加到450ms,从70000增加到200000

...
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))
我怎样才能短路不存在或加速此查询?在执行查询之前,我尝试添加一个位值并检查表值参数中是否有行。我找到的唯一方法是有两个查询,然后执行一个查询。如果我不得不修改一大堆查询或向混合中添加多个表值参数,那就不太好了

提前谢谢

编辑:

表值参数的比较:

    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))
    AND ((@rID) OR (r.ID = @rID))
和整数参数:

    AND (NOT EXISTS (SELECT Null FROM @rIDs) OR r.ID IN (SELECT r FROM @rIDs))
    AND ((@rID) OR (r.ID = @rID))
在使用TVP编译0行和整数参数null后,显示了类似的执行速度。我假设查询优化程序在正确的庄园短路,而我之前的比较不正确。执行计划将上述成本分成55%和45%,这是可以接受的。虽然当TVP中有更多行时,分割不会改变,但生成报告的时间会增加,因为必须从磁盘读取更多页面。有趣

if exists (select * from @rIDs)
    begin
    .... -- query with TVP
    end
else
    begin
    .... -- query without TVP
    end

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

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

为了更具体地回答您的问题,您可以将示例的最后一行更改为 并且存在(从@rIDs中选择r,其中r=r.ID,而非r为空)


如果你能发布执行计划,我可以给你一个更好的答案。单击显示估计的执行计划,右键单击执行计划并选择将执行计划另存为…

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

您是否尝试过
选项(重新编译)
在不缓存执行计划的情况下检查性能?我尝试了选项(重新编译),查询时间增加了两倍。ThanksI会说,
回报*可能*是巨大的
,而不是笼统地说,暗示这是应该一直这样做的方式。另外,您发布的语法不正确:
并且在…
中存在r.ID?嗨,John,我可以向表中添加一个索引,我的问题是如果TVP没有行,那么我希望索引扫描不相关。我也在中尝试了EXISTS r.ID,但它抱怨语法问题,这是2012年的功能吗?对你和Aaron都很抱歉。我在上面编辑了我的答案。我的复制粘贴出错了。你有机会看执行计划吗?我在我的问题中提到了这个方法,但是我有大量的变量和查询要考虑。如果找不到适合我的查询的解决方案,我可能不得不使用这种方法。您可以尝试
选项(重新编译)
,这将强制为每次查询执行编译。然后将使用实际行数估计查询计划。考虑到您问题中的运行时间,这肯定会有回报,因为典型的重新编译只需要20毫秒。感谢Andromar,我们非常感谢您对选项(重新编译)选项的解释