我评论了有问题的代码。当我评论这部分时,运行大约需要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,
答案 0 :(得分: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语句。
答案 1 :(得分:2)
为了使用exists
处理查询,SQL引擎需要评估该查询。您没有指定引擎,但大多数SQL引擎都不是特别擅长这一点。对于每一行,它们将遍历内部表tblIndicator
。他们甚至可以为每一行执行此操作,以在评估case
语句之前获取值。
提高性能的第一种方法是添加索引:
create index tblIndicator_fstrIndicator_flngVer_flngAccountKey on
tblIndicator(fstrIndicator, flngVer, flngAccountKey)
提高性能的第二种方法是将其更改为left outer join
。如果最多只有一行匹配,那么这很容易。如果您可能有多个匹配项,那么查询将需要更多工作。