1

Привет У меня есть хранимая процедураSQL Server 2008 хранимая процедура проблема производительности

 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 

На моем сервере DEV у меня есть данные 63k в каждой таблице

поэтому эта процедура заняла около 30 секунд, чтобы вернуть результат.

На моем сервере-изготовителе он отключается или занимает> 1 минуту. Мне интересно, что мои настольные серверные таблицы заполнены 1400 миллионами записей,

это может быть причиной.

если да, то что можно сделать, у меня есть все необходимые индексы на таблицах.

всякая помощь была бы принята с благодарностью.

благодаря

План выполнения http://www.sendspace.com/file/hk8fao

Основные утечки

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

ответ

4

Некоторые стратегии, которые могут помочь:

  1. Удалите первый ORDER BY заявление, те убийцы на сложные запросы не должны быть b e необходимо.

  2. Используйте CTE, чтобы разбить запрос на более мелкие куски, которые могут быть индивидуально адресованы.

  3. Уменьшить вложенность в первом наборе из JOIN и

  4. Извлеките второй и третий набор из соединений (Сгруппированные из них) и вставьте их во временную индексированную таблицу перед сборкой и группируя все.

  5. Вы не указали определение для function1 или function2 - пользовательские функции часто являются местом, где проблемы с производительностью могут скрыть.

Не видя плана выполнения, трудно понять, где могут быть конкретные проблемы.

+0

Я добавил план выполнения загрузки, может быть, это поможет – HaBo

+0

Я нашел проблему при вызове функции, tbfGetFOrmularyStatus() не уверен, что это лучший способ вызвать udf в sp – HaBo

3

У вас есть запрос, который выбирает данные из 4 или 5 таблиц, некоторые из них несколько раз. Трудно сказать, как улучшить без глубокого анализа того, чего вы пытаетесь достичь и какова структура таблицы на самом деле.

Размер данных определенно является проблемой; Я думаю, что совершенно очевидно, что чем больше данных нужно обрабатывать, тем длиннее будет запрос. Некоторые общие советы ... Запустите запрос напрямую и проверьте план выполнения. Это может выявить узкие места. Затем проверьте, обновляется ли статистика. Кроме того, просмотрите свои таблицы, разделение может помочь в некоторых случаях. Кроме того, вы можете попробовать изменить таблицы и создать кластеризованный индекс не на PK (как это делается по умолчанию, если не указано иное), но в другом столбце [s], чтобы ваш запрос выиграл от определенного физического порядка записей. Примечание: сделайте это, только если вы абсолютно уверены, что делаете.

Наконец, попробуйте рефакторинг вашего запроса.У меня есть ощущение, что есть лучший способ получить желаемые результаты (извините, не понимая структуру таблицы и ожидаемые результаты, я не могу сказать точное решение, но несколько соединений из тех же таблиц и группы производных таблиц выглядят не очень хорошо)