[英]Improve WITH CTE Query Optimization SQL Server 2008 R2
I have a query with multiple queries in it that get tied together at the end. 我有一个查询,其中有多个查询,最后绑定在一起。 I am working through optimizing it, to get it to run faster.
我正在努力优化它,让它运行得更快。 I was using 3 queries that created tables and inserted records into them.
我使用3个查询创建表并将记录插入其中。 I looked at my execution plan and saw that one of them was eating up 100% of the cost relative to the batch, so I changed it to the form of
;WITH CTE AS()
and that brought it's cost down to 64% of the batch. 我查看了我的执行计划,发现其中一个人正在吃掉相对于批次的100%的成本,所以我把它改成了以下形式
;WITH CTE AS()
,这使得它的成本降低到64%。批量。
Right now I see that the Hash Match (Aggreagate)
inside of this query represents 41% of the cost of this query. 现在我看到此查询中的
Hash Match (Aggreagate)
占此查询成本的41%。 From the estimated plan it also says that Missing Index (Impact 71.7682): CREATE NONCLUSTERED INDEX....
Is this something that can be done inside of the WITH
query? 根据估计的计划,它还说
Missing Index (Impact 71.7682): CREATE NONCLUSTERED INDEX....
这是否可以在WITH
查询内部完成?
Here is the part that I am trying to make more efficient 这是我试图提高效率的部分
;WITH ERCNT AS (
SELECT A.MRN
, A.VISIT_ID
, A.VISIT_DATE
, COUNT(B.VISIT_ID) AS VISIT_COUNT
FROM
(
SELECT MED_REC_NO AS MRN, vst_start_dtime AS VISIT_DATE, PT_NO AS VISIT_ID
FROM smsdss.BMH_PLM_PtAcct_V
WHERE
((
Plm_Pt_Acct_Type = 'I'
AND Adm_Source NOT IN
(
'RP'
)
)
OR pt_type = 'E')
AND vst_start_dtime >= @SD
AND vst_start_dtime < @ED
)A
LEFT JOIN
(
SELECT MED_REC_NO AS MRN, VST_START_DTIME AS VISIT_DATE, PT_NO AS VISIT_ID
FROM smsdss.BMH_PLM_PtAcct_V
WHERE
((
Plm_Pt_Acct_Type = 'I'
AND Adm_Source NOT IN
(
'RP'
)
)
OR pt_type = 'E')
AND vst_start_dtime >= @SD
AND vst_start_dtime < @ED
)B
ON A.MRN = B.MRN
AND A.VISIT_DATE > B.VISIT_DATE
--AND A.VISIT_DATE < B.VISIT_DATE
GROUP BY A.MRN, A.VISIT_ID, A.VISIT_DATE
)
If I need to provide additional information please let me know. 如果我需要提供其他信息,请告诉我。
Thank you, 谢谢,
So the problem is the left join between A and B. I assume you cannot create the index suggested by query engine. 所以问题是A和B之间的左连接。我假设您无法创建查询引擎建议的索引。 What about using table variable to store the result of the sub-query and have the index there?
那么使用表变量来存储子查询的结果并在那里有索引呢? You can then use that table in your CTE.
然后,您可以在CTE中使用该表。 Following pseudo-code should give you the idea:
遵循伪代码应该给你的想法:
DECLARE @tmp TABLE
(
MRN ???, VISIT_DATE ???, visit_id ???, PRIMARY KEY(MRN, VISIT_DATE)
)
INSERT INTO @tmp
SELECT MED_REC_NO AS MRN, vst_start_dtime AS VISIT_DATE, PT_NO AS VISIT_ID
FROM smsdss.BMH_PLM_PtAcct_V
WHERE
((
Plm_Pt_Acct_Type = 'I'
AND Adm_Source NOT IN
(
'RP'
)
)
OR pt_type = 'E')
AND vst_start_dtime >= @SD
AND vst_start_dtime < @ED
;WITH ERCNT AS (
SELECT A.MRN
, A.VISIT_ID
, A.VISIT_DATE
, COUNT(B.VISIT_ID) AS VISIT_COUNT
FROM @tmp A
LEFT JOIN @tmp B
ON A.MRN = B.MRN
AND A.VISIT_DATE > B.VISIT_DATE
GROUP BY A.MRN, A.VISIT_ID, A.VISIT_DATE
)
Took me a while to understand the difference between (...)A
and (...)B
. 花了一些时间来理解
(...)A
和(...)B
之间的区别。 Wouldn't it be more readable to use a correlated subquery like this? 使用像这样的相关子查询会不会更具可读性? => IMHO it might even be more efficient as the amount of data to aggregate is going to be smaller.
=>恕我直言,它甚至可能更有效,因为要聚合的数据量将会更小。 If you can shortcut
Plm_Pt_Acct_Type
that would probably make it even a bit faster but I don't have enough info on the tables to know if that would result in the same results .. (probably not I think). 如果您可以快捷方式
Plm_Pt_Acct_Type
,它可能会使它更快,但我没有足够的信息表,以了解是否会导致相同的结果..(可能不是我认为)。 There is another possibility to somehow shortcut B.vst_start_dtime
, @SD
, B.vst_start_dtime
, @ED
and A.vst_start_dtime
in the subquery, but I don't have time to think it through right now =) 还有另一种可能性以某种方式在子查询中快捷地
B.vst_start_dtime
, @SD
, B.vst_start_dtime
, @ED
和A.vst_start_dtime
,但我现在没有时间考虑它=)
PS: having more info on the actual tables (constraints, indexes, rowcount, etc) + a print-screen of the actual execution plan would probably help a lot. PS:有关实际表格(约束,索引,行数等)的更多信息+实际执行计划的打印屏幕可能会有很大帮助。
;WITH ERCNT AS (SELECT MRN = MED_REC_NO,
VISIT_ID = PT_NO,
VISIT_DATE = vst_start_dtime,
VISIT_COUNT = ( SELECT COUNT(*)
FROM smsdss.BMH_PLM_PtAcct_V B
WHERE -- can we simply assume B.Plm_Pt_Acct_Type = A.Plm_Pt_Acct_Type ??
((
B.Plm_Pt_Acct_Type = 'I'
AND B.Adm_Source NOT IN
(
'RP'
)
)
OR B.pt_type = 'E')
AND B.vst_start_dtime >= @SD
AND B.vst_start_dtime < @ED
-- 'join'
AND A.MED_REC_NO = B.MED_REC_NO
AND A.PT_NO = B.PT_NO
AND A.vst_start_dtime > B.vst_start_dtime
)
FROM smsdss.BMH_PLM_PtAcct_V A
WHERE
((
A.Plm_Pt_Acct_Type = 'I'
AND A.Adm_Source NOT IN
(
'RP'
)
)
OR A.pt_type = 'E')
AND A.vst_start_dtime >= @SD
AND A.vst_start_dtime < @ED
)
SELECT * FROM ERCNT
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.