繁体   English   中英

改进CTE查询优化SQL Server 2008 R2

[英]Improve WITH CTE Query Optimization SQL Server 2008 R2

我有一个查询,其中有多个查询,最后绑定在一起。 我正在努力优化它,让它运行得更快。 我使用3个查询创建表并将记录插入其中。 我查看了我的执行计划,发现其中一个人正在吃掉相对于批次的100%的成本,所以我把它改成了以下形式;WITH CTE AS() ,这使得它的成本降低到64%。批量。

现在我看到此查询中的Hash Match (Aggreagate)占此查询成本的41%。 根据估计的计划,它还说Missing Index (Impact 71.7682): CREATE NONCLUSTERED INDEX....这是否可以在WITH查询内部完成?

这是我试图提高效率的部分

;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
)

如果我需要提供其他信息,请告诉我。

谢谢,

所以问题是A和B之间的左连接。我假设您无法创建查询引擎建议的索引。 那么使用表变量来存储子查询的结果并在那里有索引呢? 然后,您可以在CTE中使用该表。 遵循伪代码应该给你的想法:

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
)

花了一些时间来理解(...)A(...)B之间的区别。 使用像这样的相关子查询会不会更具可读性? =>恕我直言,它甚至可能更有效,因为要聚合的数据量将会更小。 如果您可以快捷方式 Plm_Pt_Acct_Type ,它可能会使它更快,但我没有足够的信息表,以了解是否会导致相同的结果..(可能不是我认为)。 还有另一种可能性以某种方式在子查询中快捷地 B.vst_start_dtime@SDB.vst_start_dtime@EDA.vst_start_dtime ,但我现在没有时间考虑它=)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM