SQL Server 2008存储过程性能问题

时间:2012-06-24 00:05:59

标签: sql-server stored-procedures database-performance timeoutexception

您好我有一个存储过程

     ALTER PROCEDURE [dbo].[usp_EP_GetTherapeuticalALternates]
    (
      @NDCNumber CHAR(11) ,
      @patientid INT ,
      @pbmid INT
    )
AS 
    BEGIN
        TRUNCATE TABLE TempTherapeuticAlt
        INSERT  INTO TempTherapeuticAlt
                SELECT  --PR.ProductID AS MedicationID ,
                        NULL AS MedicationID ,
                        PR.ePrescribingName AS MedicationName ,
                        U.Strength AS MedicationStrength ,
                        FRM.FormName AS MedicationForm ,
                        PR.DEAClassificationID AS DEASchedule ,
                        NULL AS NDCNumber
        --INTO    #myTemp
                FROM    DatabaseTwo.dbo.Product PR
                        JOIN ( SELECT   MP.MarketedProductID
                               FROM     DatabaseTwo.dbo.Therapeutic_Concept_Tree_Specific_Product TCTSP
                                        JOIN DatabaseTwo.dbo.Marketed_Product MP ON MP.SpecificProductID = TCTSP.SpecificProductID
                                        JOIN ( SELECT   TCTSP.TherapeuticConceptTreeID
                                               FROM     DatabaseTwo.dbo.Marketed_Product MP
                                                        JOIN DatabaseTwo.dbo.Therapeutic_Concept_Tree_Specific_Product TCTSP ON MP.SpecificProductID = TCTSP.SpecificProductID
                                                        JOIN ( SELECT
                                                              PR.MarketedProductID
                                                              FROM
                                                              DatabaseTwo.dbo.Package PA
                                                              JOIN DatabaseTwo.dbo.Product PR ON PA.ProductID = PR.ProductID
                                                              WHERE
                                                              PA.NDC11 = @NDCNumber
                                                             ) 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     DatabaseTwo.dbo.Product AS P
                                        INNER JOIN DatabaseTwo.dbo.Marketed_Product
                                        AS M ON P.MarketedProductID = M.MarketedProductID
                                        INNER JOIN DatabaseTwo.dbo.Specific_Product
                                        AS S ON M.SpecificProductID = S.SpecificProductID
                                        LEFT OUTER JOIN DatabaseTwo.dbo.OrderableName_Combined
                                        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     DatabaseTwo.dbo.Package AS PA
                                        INNER JOIN DatabaseTwo.dbo.Script_Form
                                        AS S ON PA.NCPDPScriptFormCode = S.NCPDPScriptFormCode
                                        INNER JOIN DatabaseTwo.dbo.FormCode AS F ON S.FormName = F.FormName
                               GROUP BY PA.ProductID ,
                                        S.ScriptFormID ,
                                        F.Code ,
                                        S.FormName
                             ) FRM ON PR.ProductID = FRM.ProductID
                            WHERE   
                            ( PR.OffMarketDate IS NULL )
        OR ( PR.OffMarketDate = '' )
        OR (PR.OffMarketDate = '1899-12-30 00:00:00.000')
        OR ( PR.OffMarketDate <> '1899-12-30 00:00:00.000'
             AND DATEDIFF(dd, GETDATE(),PR.OffMarketDate) > 0
           )
                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 ,
                copay.PharmacyType,
                dbo.udf_EP_GetBrandGeneric(LL.ProductID) AS BrandGeneric
        FROM    TempTherapeuticAlt temp
                OUTER APPLY ( SELECT TOP 1
                                        ProductID
                              FROM      DatabaseTwo.dbo.Product
                              WHERE     ePrescribingName = temp.MedicationName
                            ) AS LL
                OUTER APPLY [dbo].[udf_EP_tbfGetFormularyStatus](@patientid,
                                                              LL.ProductID,
                                                              @pbmid) AS fs
                OUTER APPLY ( SELECT TOP 1
                                        *
                              FROM      udf_EP_CopayDetails(LL.ProductID,
                                                            @PBMID,
                                                            fs.ReturnFormulary)
                            ) copay
        --ORDER BY LL.ProductID
        TRUNCATE TABLE TempTherapeuticAlt
    END

在我的开发服务器上,我在每个表中都有63k的数据

所以这个过程大约需要30秒才能返回结果。

在我的生产服务器上,它超时,或者花费> 1分钟。 我想知道我的生产服务器表已满了1400万条记录,

这可能是一个原因。

如果是这样,可以做什么,我在表上都需要索引。

任何帮助将不胜感激。

感谢

执行计划 http://www.sendspace.com/file/hk8fao

重大泄漏

OUTER APPLY [dbo].[udf_EP_tbfGetFormularyStatus](@patientid,
                                                              LL.ProductID,
                                                              @pbmid) AS fs

2 个答案:

答案 0 :(得分:4)

一些可能有用的策略:

  1. 删除第一个ORDER BY语句,这些都是复杂查询的杀手锏。

  2. 使用CTE将查询分解为可以单独处理的较小部分。

  3. 减少第一组JOIN中的嵌套

  4. 提取第二组和第三组连接(GROUPED连接),并在连接和分组所有内容之前将它们插入临时索引表中。

  5. 您未包含function1function2的定义 - 自定义函数通常是性能问题可隐藏的地方。

  6. 如果没有看到执行计划,很难看出特定问题可能在哪里。

答案 1 :(得分:3)

您有一个查询从4或5个表中选择数据,其中一些表多次。如果不深入分析你想要实现的目标以及实际上是什么表结构,很难说如何改进。

数据大小肯定是个问题;我认为很明显,必须处理的数据越多,查询所需的时间就越长。一些一般性建议...直接运行查询并检查执行计划。它可能揭示瓶颈。然后检查统计数据是否是最新的。此外,检查您的表,在某些情况下,分区可能会有很大帮助。此外,您可以尝试更改表并在PK上创建聚簇索引(除非另有指定,否则默认情况下已完成),但在其他列[s]上,因此您的查询将受益于某些物理记录顺序。注意:只有在你完全确定自己在做什么的情况下才能这样做。

最后,尝试重构您的查询。我有一种感觉,有更好的方法来获得理想的结果(对不起,没有理解表结构和预期结果我不能说出确切的解决方案,但是同一个表和一堆派生表的多个连接对我来说不太好看)