【问题标题】:Slow running BIDS report query...OR clauses in WHERE branch using IN sub queries运行缓慢的 BIDS 报告查询...在 WHERE 分支中使用 IN 子查询的 OR 子句
【发布时间】:2014-12-10 22:27:45
【问题描述】:

我有一个包含 3 个子报表和几个要在每个报表中优化的查询的报表。第一个在 WHERE 分支中有几个 OR 子句,并且 OR 正在通过拉取子查询的 IN 选项进行过滤。

我说这主要来自阅读this SO post。特别是 LBushkin 的第二点。

我在 TSQL 方面不是最出色的,但我知道这足以认为这是非常低效的。我想我需要做两件事。

  1. 我知道我需要为相关表添加索引。

  2. 我认为查询可以大大增强。

看来我的第一步是改进查询。从那里我可以查看涉及哪些列和表,从而确定索引。

此时我还没有发布表架构,因为我正在寻找更多选项/注意事项,例如使用 cte 替换所有 IN 子查询。

如果需要,我一定会发布任何有用的信息,例如物理阅读等。

SELECT DISTINCT 
  auth.icm_authorizationid, 
  auth.icm_documentnumber
FROM 
  Filteredicm_servicecost AS servicecost 

INNER JOIN Filteredicm_authorization AS auth ON 
auth.icm_authorizationid = servicecost.icm_authorizationid 

INNER JOIN Filteredicm_service AS service ON 
service.icm_serviceid = servicecost.icm_serviceid 

INNER JOIN Filteredicm_case AS cases ON 
service.icm_caseid = cases.icm_caseid

WHERE
  (cases.icm_caseid IN
    (SELECT icm_caseid FROM Filteredicm_case AS CRMAF_Filteredicm_case)) 

  OR (service.icm_serviceid IN
    (SELECT icm_serviceid FROM Filteredicm_service AS CRMAF_Filteredicm_service)) 

  OR (servicecost.icm_servicecostid IN
    (SELECT icm_servicecostid FROM Filteredicm_servicecost AS CRMAF_Filteredicm_servicecost)) 

  OR (auth.icm_authorizationid IN
    (SELECT icm_authorizationid FROM Filteredicm_authorization AS CRMAF_Filteredicm_authorization)) 

【问题讨论】:

  • 我相信您可以删除所有 where 条件,并且您应该得到与引用原始表相同的结果(case to caseservice to serviceservicecost to servicecost 和 @ 987654327@)

标签: sql-server sql-server-2008 tsql


【解决方案1】:

EXISTS 通常比IN 快得多,因为查询引擎能够更好地优化它。

试试这个:

WHERE EXISTS (SELECT 1 FROM FROM Filteredicm_case WHERE icm_caseid = cases.icm_caseid)
    OR EXISTS (SELECT 1 FROM Filteredicm_service WHERE icm_serviceid = service.icm_serviceid)
    OR EXISTS (SELECT 1 FROM Filteredicm_servicecost WHERE icm_servicecostid = servicecost.icm_servicecostid)
    OR EXISTS (SELECT 1 FROM Filteredicm_authorization WHERE icm_authorizationid = auth.icm_authorizationid)

此外,Filteredicm_case.icm_caseid 上的索引、Filteredicm_service.icm_serviceid 上的索引、Filteredicm_servicecost.icm_servicecostid 上的索引和Filteredicm_authorization.icm_authorizationid 上的索引将提高此查询的性能。但是,它们看起来应该已经是键了,所以我怀疑索引已经存在。

但是,除非我读错了,否则这个 WHERE 子句永远不会评估为 true。

你写的子句是WHERE cases.icm_caseid IN (SELECT icm_caseid FROM Filteredicm_case AS CRMAF_Filteredicm_case)。但是,casesFilteredicm_case 的别名。这相当于WHERE Filteredicm_case.icm_caseid IN (SELECT icm_caseid FROM Filteredicm_case AS CRMAF_Filteredicm_case)。只要Filteredicm_case.icm_caseid 不是NULL,这就是正确的。

WHERE 子句中的其余部分存在相同的逻辑错误:

(service.icm_serviceid IN (SELECT icm_serviceid FROM Filteredicm_service AS CRMAF_Filteredicm_service))

serviceFilteredicm_service 的别名。只要icm_serviceid 不为空,这始终是正确的

(servicecost.icm_servicecostid IN (SELECT icm_servicecostid FROM Filteredicm_servicecost AS CRMAF_Filteredicm_servicecost)) 

servicecostFilteredicm_servicecost 的别名。只要icm_servicecostid 不为空,这始终是正确的。

(auth.icm_authorizationid IN (SELECT icm_authorizationid FROM Filteredicm_authorization AS CRMAF_Filteredicm_authorization))

authFilteredicm_authorization 的别名。只要icm_authorizationid 不为空,这始终是正确的。

我不明白你要完成什么。

【讨论】:

  • 完全正确!这个查询对我来说已经三个小时了,有些事情对我来说也是如此,但就像我在 OP 中所说的那样,我在 TSQL 方面不是最棒的,所以我想我会得到一些更有知识的输入......你肯定提供了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2020-10-13
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多