慢速运行BIDS报告查询...使用IN子查询在WHERE分支中使用OR子句

时间:2014-10-15 18:20:16

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

我有一份报告,其中包含3个子报告和几个要在每个报告中进行优化的查询。第一个在WHERE分支中有几个OR子句,OR正在通过IN选项进行过滤,这些选项会拉动子查询。

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

我不是TSQL的最佳人选,但我知道这个效率非常低。我想我需要做两件事。

  1. 我知道我需要为所涉及的表添加索引。

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

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

    此时我还没有发布表格模式,因为我正在寻找更多选项/注意事项,例如使用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)) 
    

1 个答案:

答案 0 :(得分: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条款无法评估除真实以外的其他任何内容。

您撰写的条款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不为空,就始终为真。

我不明白你想要完成的事情。