这是一个存储过程..这个if语句,然后我做了一点工作。 @AsOfDate是 date 数据类型的传入变量。我的问题是为什么我通过删除最内层存在来获得更好的性能,但只有当整个语句处于IF EXISTS 时才会获得更好的效果?
两个表:
说明:
if exists (select 1
from dbo.TXXX_InventoryDetail o
where exists (select 1
from dbo.TXXX_InventoryFull i
where i.C001_AsOfDate= o.C001_AsOfDate
and i.C001_ProductID=o.C001_ProductID
and i.C001_StoreNumber=o.C001_StoreNumber
and i.C001_AsOfDate=@AsOfDate
and (i.C001_LastModelDate!=o.C001_LastModelDate
or o.C001_InventoryQty!=o.C001_InventoryQty
or i.C001_OnOrderQty!=o.C001_OnOrderQty
or i.C001_TBOQty!=o.C001_TBOQty
or i.C001_ModelQty!=o.C001_ModelQty
or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty
or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending
or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess
or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut))
and o.C001_AsOfDate=@AsOfDate)
输出:
如果我删除第二个存在并进行加入:
if exists (select 1
from dbo.TXXX_InventoryDetail o,
dbo.TXXX_InventoryFull i
where i.C001_AsOfDate= o.C001_AsOfDate
and i.C001_ProductID=o.C001_ProductID
and i.C001_StoreNumber=o.C001_StoreNumber
and i.C001_AsOfDate=@AsOfDate
and (i.C001_LastModelDate!=o.C001_LastModelDate
or o.C001_InventoryQty!=o.C001_InventoryQty
or i.C001_OnOrderQty!=o.C001_OnOrderQty
or i.C001_TBOQty!=o.C001_TBOQty
or i.C001_ModelQty!=o.C001_ModelQty
or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty
or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending
or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess
or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut)
and o.C001_AsOfDate=@AsOfDate)
输出:
现在..我认为如果存在的原因是,如果我删除它并执行选择计数(*),就像这样:
select COUNT(*)
from dbo.T001_InventoryDetail o
where exists (select 1
from dbo.TXXX_InventoryFull i
where i.C001_AsOfDate= o.C001_AsOfDate
and i.C001_ProductID=o.C001_ProductID
and i.C001_StoreNumber=o.C001_StoreNumber
and i.C001_AsOfDate=@AsOfDate
and (i.C001_LastModelDate!=o.C001_LastModelDate
or o.C001_InventoryQty!=o.C001_InventoryQty
or i.C001_OnOrderQty!=o.C001_OnOrderQty
or i.C001_TBOQty!=o.C001_TBOQty
or i.C001_ModelQty!=o.C001_ModelQty
or i.C001_TBOAdjustQty!=o.C001_TBOAdjustQty
or i.C001_ReturnQtyPending!=o.C001_ReturnQtyPending
or i.C001_ReturnQtyInProcess!=o.C001_ReturnQtyInProcess
or i.C001_ReturnQtyDueOut!=o.C001_ReturnQtyDueOut))
and o.C001_AsOfDate=@AsOfDate
答案 0 :(得分:2)
通常认为应该避免在谓词中执行协调的子查询,因为这些子查询会强制嵌套循环连接。在查询大型数据集时,尤其是在尝试发现集合之间存在差异的情况下,允许查询优化器在散列,合并和嵌套循环算法之间动态选择是很重要的,如果使用协调子查询构造查询,这可能是不可能的。 。最好在FROM子句中将它们创建为派生表。
答案 1 :(得分:1)
我在SQL 08 R2服务器上使用EXISTS语句发现了类似的问题,其中完全相同的语句在SQL 08和SQL 05上运行良好。
我发现改变了像
这样的东西WHILE EXISTS(SELECT * FROM X)
会超级慢,但是:
WHILE ISNULL((SELECT TOP 1 ID FROM X), 0) <> 0
再次跑得很快。
对我而言,这似乎是一个R2问题......
答案 2 :(得分:0)
我猜你使用联接时得到的计划大不相同。也许行数(非常大的外部表,较小的内部表)的不平衡使得优化器适合,但是它可以通过连接更容易地消除行(您可能会看到具有更差查询的其他循环操作符)。在没有看到计划或能够重现的情况下难以真正猜测,但是你应该始终尽可能地在计划的早期消除大多数行。通过几个运算符/子查询回退数百万行只是为了在计划的后期消除大部分行,几乎肯定会产生更差的性能。