Sql Server 查询优化技巧

Posted

技术标签:

【中文标题】Sql Server 查询优化技巧【英文标题】:Sql Server queries optimization techniques 【发布时间】:2012-05-27 00:04:14 【问题描述】:

我的存储过程需要很长时间才能执行。 任何人都可以建议我做什么来加快存储过程,除了使用一些好的做法来写下查询。 我听说过创建索引,但我不确定它们是什么。 请建议所有加快查询速度的最佳方法。 谢谢

CREATE PROCEDURE [dbo].[usp_GetAlternates]
(
  @NNumber CHAR(11) ,
  @pid INT ,
  @pbmid INT
)
AS 
BEGIN
    TRUNCATE TABLE TempTherapeuticAlt
    INSERT  INTO TempTherapeuticAlt
            SELECT  NULL AS MedicationID ,
                    PR.ePrescribingName AS MedicationName ,
                    U.Strength AS MedicationStrength ,
                    FRM.FormName AS MedicationForm ,
                    PR.DEAClassificationID AS DEASchedule ,
                    NULL AS NDCNumber
            FROM    Product PR
                    JOIN ( SELECT   MP.MarketedProductID
                           FROM     table2 TCTSP
                                    JOIN table3 MP ON MP.SpecificProductID = TCTSP.SpecificProductID
                                    JOIN ( SELECT   TCTSP.TherapeuticConceptTreeID
                                           FROM     table3 MP
                                                    JOIN table2 TCTSP ON MP.SpecificProductID = TCTSP.SpecificProductID
                                                    JOIN ( SELECT
                                                          PR.MarketedProductID
                                                          FROM
                                                          table4 PA
                                                          JOIN Product PR ON PA.ProductID = PR.ProductID
                                                          WHERE
                                                          PA.NDC11 = @NNumber
                                                         ) PAPA ON MP.MarketedProductID = PAPA.MarketedProductID
                                         ) xxx ON TCTSP.TherapeuticConceptTreeID = xxx.TherapeuticConceptTreeID
                         ) MPI ON PR.MarketedProductID = MPI.MarketedProductID
                    JOIN ( SELECT   P.ProductID ,
                                    O.Strength ,
                                    O.Unit
                           FROM     Product AS P
                                    INNER JOIN table3 AS M ON P.MarketedProductID = M.MarketedProductID
                                    INNER JOIN table5 AS S ON M.SpecificProductID = S.SpecificProductID
                                    LEFT OUTER JOIN table6 AS O ON S.SpecificProductID = O.SpecificProductID
                           GROUP BY P.ProductID ,
                                    O.Strength ,
                                    O.Unit
                         ) U ON PR.ProductID = U.ProductID
                    JOIN ( SELECT   PA.ProductID ,
                                    S.ScriptFormID ,
                                    F.Code AS NCPDPScriptFormCode ,
                                    S.FormName
                           FROM     table4 AS PA
                                    INNER JOIN table7 AS S ON PA.NCPDPScriptFormCode = S.NCPDPScriptFormCode
                                    INNER JOIN table8 AS F ON S.FormName = F.FormName
                           GROUP BY PA.ProductID ,
                                    S.ScriptFormID ,
                                    F.Code ,
                                    S.FormName
                         ) FRM ON PR.ProductID = FRM.ProductID
            GROUP BY PR.ePrescribingName ,
                    U.Strength ,
                    FRM.FormName ,
                    PR.DEAClassificationID
            ORDER BY pr.ePrescribingName


    SELECT  LL.ProductID AS MedicationID ,
            temp.MedicationName ,
            temp.MedicationStrength ,
            temp.MedicationForm ,
            temp.DEASchedule ,
            temp.NDCNumber ,
            fs.[ReturnFormulary] AS FormularyStatus ,
            copay.CopaTier ,
            copay.FirstCopayTerm ,
            copay.FlatCopayAmount ,
            copay.PercentageCopay
    FROM    TempTherapeuticAlt temp
            OUTER APPLY ( SELECT TOP 1
                                    ProductID
                          FROM      Product
                          WHERE     ePrescribingName = temp.MedicationName
                        ) AS LL
            OUTER APPLY function1(@pid, LL.ProductID, @pbmid) AS fs
            OUTER APPLY function2(LL.ProductID, @pbmid) AS copay
    ORDER BY LL.ProductID

    TRUNCATE TABLE TempTherapeuticAlt
END

【问题讨论】:

如果您需要帮助,请向我们展示存储过程 马上开始,我要集中精力加速存储过程的第一个地方是函数(外部应用在底部附近)。他们可以而且经常确实会彻底破坏性能。要知道是否是这种情况,请制作一个已删除它们的存储过程版本,并查看它所产生的差异。 TempTherapeuticAlt 通常返回多少行? 【参考方案1】:

这里有几个:

    您应该为 WHERE 子句中的每一列都有索引。看 你的 SQL 语言如何做到这一点。 了解如何解释计划并查看慢的地方。 存储过程语言是函数式的,不是基于集合的。使用 JOIN,不要陷入 (n+1) 查询/迭代陷阱。 了解使用某些函数如何强制您在 WHERE 子句中进行 TABLE SCAN。

【讨论】:

3) 解释计划:是的!!!很好的建议。 1)索引:错误(如果按字面意思理解)。您应该考虑索引:是的。 “必须有索引”:否 4) 存储过程提供基于集合 (SQL) 和过程的最佳。尽可能使用集合,而不是逐项处理。 2)“where”中的列顺序导致可以有所作为。有时会有巨大的差异。 关于位置的顺序见***.com/questions/642784/…。我的经验是使用 MS Sql Server,我很少发现摆弄 WHERE 表达式的顺序会产生任何影响。 1) @paulsm4 是对的。存储过程中对特定表的所有 where 子句引用只需要一个精心选择的索引。

以上是关于Sql Server 查询优化技巧的主要内容,如果未能解决你的问题,请参考以下文章

关于优化在大量数据上执行的 Oracle SQL 查询的建议/技巧

30个MySQL千万级大数据SQL查询优化技巧详解

SQL Server查询优化方法

MySQL语句优化技巧?

这些SQL优化技巧握在手,面试可以横着走……

30个mysql千万级大数据SQL查询优化技巧详解