如果存在子查询的查询优化

Query Optimization for if exists sub query

我正在尝试优化下面的查询

if exists (select 1 
           from GHUB_DISCREPANCY_REPORT (NOLOCK) 
           where PARTNO = @currentpn and orderID = @oldorderid + 1 
             and (Discr_Fox_Available = 'Y' 
                  or Discr_Fox_NC = 'Y' or Discr_FOC_Available = 'Y' 
                  or Discr_FOC_NC = 'Y' or Discr_Cpa_Available = 'Y' 
                  or Discr_Cpa_NC = 'Y' or Discr_Fox_Tot = 'Y' 
                  or Discr_FOC_Tot = 'Y' or Discr_Cpa_Tot = 'Y'))

我索引了主键、PartNo、Aging 和 OrderID 列。

还有其他方法可以优化此查询吗?

求推荐!

首先,尝试在 GHUB_DISCREPANCY_REPORT(PARTNO, orderId) 上建立索引。这可能对您的查询有很大的帮助。

如果您仍然有性能问题,一种方法是使用分离查询,每个查询都可以使用单独的索引进行优化。

if exists (select 1 
           from GHUB_DISCREPANCY_REPORT (NOLOCK) 
           where PARTNO = @currentpn and orderID = @oldorderid and Discr_Fox_Available = 'Y' 
          ) or
    . . .

然后每个组合都有一个单独的复合索引:GHUB_DISCREPANCY_REPORT(PARTNO, orderId, Discr_Fox_Available)。这是一个很大的索引开销,但可能是值得的。

另一个想法是将所有标志合并为一个:

alter table GHUB_DISCREPANCY_REPORT 
    add Any_Flags as (case when (Discr_Fox_Available = 'Y' 
                  or Discr_Fox_NC = 'Y' or Discr_FOC_Available = 'Y' 
                  or Discr_FOC_NC = 'Y' or Discr_Cpa_Available = 'Y' 
                  or Discr_Cpa_NC = 'Y' or Discr_Fox_Tot = 'Y' 
                  or Discr_FOC_Tot = 'Y' or Discr_Cpa_Tot = 'Y' then 'Y' else 'N' end);

您可以在计算列上添加索引,然后在查询中使用该值:

create index idx_GHUB_DISCREPANCY_REPORT_anyflags on GHUB_DISCREPANCY_REPORT(PARTNO, OrderId, AnyFlags);

if exists (select 1 
           from GHUB_DISCREPANCY_REPORT (NOLOCK) 
           where PARTNO = @currentpn and orderID = @oldorderid and AnyFlags = 'Y' 
          ) 
在 "if exists"(子查询)部分,

"top 1 1 from tbl_name" 比“select 1”提供更好的性能。

参考this discussion

在使用 "top 1 1" 后,估计行数从我的 135765 减少到 1。