我有一份报告,其中包含3个子报告和几个要在每个报告中进行优化的查询。第一个在WHERE分支中有几个OR子句,OR正在通过IN选项进行过滤,这些选项会拉动子查询。
我这主要是从阅读this SO post来说。特别是LBushkin的第二点。
我不是TSQL的最佳人选,但我知道这个效率非常低。我想我需要做两件事。
我知道我需要为所涉及的表添加索引。
我认为可以大大增强查询。
所以我的第一步似乎是改进查询。从那里我可以看看涉及哪些列和表,从而确定索引。
此时我还没有发布表格模式,因为我正在寻找更多选项/注意事项,例如使用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))
答案 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)
。但是,cases
是Filteredicm_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))
service
是Filteredicm_service
的别名。只要icm_serviceid
不为空
(servicecost.icm_servicecostid IN (SELECT icm_servicecostid FROM Filteredicm_servicecost AS CRMAF_Filteredicm_servicecost))
servicecost
是Filteredicm_servicecost
的别名。只要icm_servicecostid
不为空,就始终为真。
(auth.icm_authorizationid IN (SELECT icm_authorizationid FROM Filteredicm_authorization AS CRMAF_Filteredicm_authorization))
auth
是Filteredicm_authorization
的别名。只要icm_authorizationid
不为空,就始终为真。
我不明白你想要完成的事情。