0

我注释掉了有问题的代码。当我注释掉这部分时,运行大约需要 5 秒。

加上额外的条件,大约需要一年(好吧,大概是 10 分钟)。

谢谢你们的帮助!

SELECT  t.account as fstrAccount,
        t.idno as flngID,
        CASE    
        WHEN t.fstrType = '' THEN '' 

        WHEN wd.fstrWorkType    = 'SUSIN1'
        AND wd.fstrOwner        =  ' ' 
        AND wd.flngworkkey      =  wr.flngworkkey 
        AND wr.fstrAccountType  <> '007' 
        AND wr.fblnOpen         =  1 
        --AND   EXISTS  
        --  (SELECT 1 
        --  FROM    tblIndicator id
        --  WHERE   id.fstrIndicator   = 'EIWTCH' 
        --  AND id.flngVer         = 0 
        --  AND id.flngAccountKey  = wd.flngAccountKey)
        THEN 'Suspended for Audit Indicator - EIC Watch For'
        ELSE    t.fstrTaskSource + '_TYP_' + t.fstrType 
        END AS fstrType,
4

2 回答 2

4

有时,EXISTS 子句似乎会导致数据库的不良行为,即使它应该落在索引上——复杂的查询只会让数据库优化器感到困惑,最终会为主表中的每一行重新运行相关的子查询。

当所有其他优化都失败时,我通常通过将其重写为左外连接并检查连接表中非 NULL 列上的 NULL 来解决此问题。这有时使优化器可以理解查询,并且它会执行正确的索引连接。

对于您的 SQL,它可能类似于:

SELECT 
   t.account as fstrAccount,
   t.idno as flngID,
   CASE
      ...
      AND wr.fblnOpen = 1
      AND NOT id.flngVer IS NULL
      ...
FROM
      ...
LEFT OUTER JOIN
    tblIndicator id
ON
    id.fstrIndicator = 'EIWTCH'
    AND id.flngVer = 0
    AND id.flngAccountKey = wd.flngAccountKey

这假设每个“wd”最多有一个“id”,使用那个 ON 子句。如果可以有多个匹配项,则可以使用像 MAX() 这样的聚合函数,并依赖于这样一个事实,即如果没有记录,聚合函数将返回 NULL。在这种情况下,“AND NOT id.flngVer IS NULL”变为“AND NOT MAX(id.flngVer) IS NULL”。如果您使用聚合函数,您还必须添加必要的 GROUP BY 语句。

于 2013-11-06T20:51:11.000 回答
2

为了使用 处理查询exists,SQL 引擎需要评估该查询。您没有指定引擎,但大多数 SQL 引擎在这方面并不是特别擅长。tblIndicator他们将在每一行的内表中循环。他们甚至可能对每一行都这样做,以便在评估case语句之前获取值。

提高性能的第一种方法是添加索引:

create index tblIndicator_fstrIndicator_flngVer_flngAccountKey on
    tblIndicator(fstrIndicator, flngVer, flngAccountKey)

提高性能的第二种方法是将其更改为left outer join. 如果最多匹配一行,那么这很容易。如果您可能有多个匹配项,那么查询将需要更多的工作。

于 2013-11-06T20:46:11.117 回答