StoredProcedure性能改进

时间:2018-10-04 12:18:48

标签: sql sql-server

请在下面检查Microsoft SQL StoredProcedure查询。有了这个查询,我变得很慢,无法完成该过程。仅1000/2000条记录需要20秒钟以上的时间才能执行。现在我的问题是如何调整该查询以提高其性能?我不需要整个工作查询,但是我需要专家的建议,我该怎么做才能改善其性能?有没有更好的短方法来编写相同的查询?请指教。预先感谢

性能不佳的SQL:

USE [Analytics]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER procedure [vision].[SancusoReferralExceptionsReport]
as
begin
 Declare @programid varchar(30) ;
 DECLARE @Startdate DATETIME = '1900-01-01'
 set @programid = '31';
     ;        
     with ProgramExceptions as
     (

            -- 1. Referring contact name should not be blank
           select 'Referral Pharmacy Contact Name should not be blank' as ExceptionReason
                 , a.AspnRxID
                 , ap.PrescriptionID
              from [ArmadaRX].aspn.ASPNRX a  
              left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = a.AspnRxID
              where a.ProgramID in (31)
              and (@Startdate is null or (a.CreatedOn between @Startdate and getdate()))
              and (a.ReferringPharmacyContact is null or rtrim(ltrim(a.ReferringPharmacyContact)) = '')


            union
            -- 2.   Received/Referral Date should not be blank
            select 'Received/Referral date should not be blank' as ExceptionReason
                  , a.AspnRxID
                  , ap.PrescriptionID
            from [ArmadaRX].aspn.ASPNRX a 
            left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = a.AspnRxID
            where a.ProgramID in (31)
            and (@Startdate is null or (a.CreatedOn between @Startdate and getdate()))
            and a.ReceivedOn is null


     ) /* end of CTE */


           select distinct
                  pe.ExceptionReason
                , pe.AspnRxID 
                , a.ProgramID
                , prg.ProgramName
                , coalesce(cp.ReferralType,a.ReferralType) ReferralType
                , a.RxType
                , a.ProgramStatus
                , a.ProgramSubstatus
                , a.ReceivedOn as ReceivedOnDate
                , a.PrescriptionDate
                , ap.FillDate
                , ap.ShipDate   
                , cp.Quantity as PrescriptionQuantity
                , ap.FillQty
                , ap.Indicator
                , a.CreatedOn as CreateDate
                , a.ModifiedOn as ModifyDate
                , a.AssignedOn as AssignDate
                , a.AcceptedOn as AcceptDate
                , a.CompletedOn as CompleteDate
                , a.CancelledOn as CancelDate
                , a.FillingPharmacyContact
                , a.ReferringPharmacyContact
                , m.MemberName as FillingPharmacyName
                , m2.MemberName as ReferringPharmacyName
                , cp.PrescriptionID
                , cp.DrugName
                , cp.Copay as PrescriptionCopay
                , a.ReferralCode
                , (select [TypeCode] from [ArmadaRX].[common].[INSURANCETYPE] where [InsuranceTypeID] = cp.InsuranceType) as InsuranceType
                , cp.InsuranceName
                , pd.NPI
                , cp.Binnumber

        from ProgramExceptions pe
          inner join [ArmadaRX].aspn.ASPNRX a on a.AspnRxID = pe.AspnRxID
          left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = pe.AspnRxID and (pe.PrescriptionID is null or ap.PrescriptionID = pe.PrescriptionID)  
          left outer join [ArmadaRX].common.PRESCRIPTION cp on cp.PrescriptionID = ap.PrescriptionID and (pe.PrescriptionID is null or cp.PrescriptionID = pe.PrescriptionID)
          left outer join ArmadaRX.aspn.PRESCRIPTIONDOCTOR pd on pd.PrescriptionID = cp.PrescriptionID
          left outer join [ArmadaRX].common.Patient p on p.patientID = a.PatientID
          left outer join [ArmadaRX].aspn.Program prg on prg.ProgramID = a.ProgramID
          left outer join ArmadaApproveRx.dbo.vMember m on m.MemberID = a.FillingPharmacyID
          left outer join ArmadaApproveRx.dbo.vMember m2 on m2.MemberID = a.ReferringPharmacyID

         where a.ProgramID in (31)
        order by pe.AspnRxID



end 

1 个答案:

答案 0 :(得分:0)

以我的经验,对大型数据集使用CTE会降低查询的性能。在将CTE切换到Temp表时,我发现性能有了很大的提高,因为这确实使我能够根据需要创建索引。下面的代码是使用CTE将OP示例查询转换为使用临时表的示例。

USE [Analytics]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER procedure [vision].[SancusoReferralExceptionsReport]
as
begin
 Declare @programid varchar(30) ;
 DECLARE @Startdate DATETIME = '1900-01-01'
 set @programid = '31';

SELECT * 
INTO #TempTable
FROM (
    -- 1. Referring contact name should not be blank
   select 'Referral Pharmacy Contact Name should not be blank' as ExceptionReason
         , a.AspnRxID
         , ap.PrescriptionID
      from [ArmadaRX].aspn.ASPNRX a  
      left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = a.AspnRxID
      where a.ProgramID in (31)
      and (@Startdate is null or (a.CreatedOn between @Startdate and getdate()))
      and (a.ReferringPharmacyContact is null or rtrim(ltrim(a.ReferringPharmacyContact)) = '')


    union
    -- 2.   Received/Referral Date should not be blank
    select 'Received/Referral date should not be blank' as ExceptionReason
          , a.AspnRxID
          , ap.PrescriptionID
    from [ArmadaRX].aspn.ASPNRX a 
    left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = a.AspnRxID
    where a.ProgramID in (31)
    and (@Startdate is null or (a.CreatedOn between @Startdate and getdate()))
    and a.ReceivedOn is null
 ) AS T
select distinct
      pe.ExceptionReason
    , pe.AspnRxID 
    , a.ProgramID
    , prg.ProgramName
    , coalesce(cp.ReferralType,a.ReferralType) ReferralType
    , a.RxType
    , a.ProgramStatus
    , a.ProgramSubstatus
    , a.ReceivedOn as ReceivedOnDate
    , a.PrescriptionDate
    , ap.FillDate
    , ap.ShipDate   
    , cp.Quantity as PrescriptionQuantity
    , ap.FillQty
    , ap.Indicator
    , a.CreatedOn as CreateDate
    , a.ModifiedOn as ModifyDate
    , a.AssignedOn as AssignDate
    , a.AcceptedOn as AcceptDate
    , a.CompletedOn as CompleteDate
    , a.CancelledOn as CancelDate
    , a.FillingPharmacyContact
    , a.ReferringPharmacyContact
    , m.MemberName as FillingPharmacyName
    , m2.MemberName as ReferringPharmacyName
    , cp.PrescriptionID
    , cp.DrugName
    , cp.Copay as PrescriptionCopay
    , a.ReferralCode
    , (select [TypeCode] from [ArmadaRX].[common].[INSURANCETYPE] where [InsuranceTypeID] = cp.InsuranceType) as InsuranceType
    , cp.InsuranceName
    , pd.NPI
    , cp.Binnumber
from #TempTable pe
  inner join [ArmadaRX].aspn.ASPNRX a on a.AspnRxID = pe.AspnRxID
  left outer join [ArmadaRX].aspn.ASPNRX_PRESCRIPTION ap on ap.AspnRxID = pe.AspnRxID and (pe.PrescriptionID is null or ap.PrescriptionID = pe.PrescriptionID)  
  left outer join [ArmadaRX].common.PRESCRIPTION cp on cp.PrescriptionID = ap.PrescriptionID and (pe.PrescriptionID is null or cp.PrescriptionID = pe.PrescriptionID)
  left outer join ArmadaRX.aspn.PRESCRIPTIONDOCTOR pd on pd.PrescriptionID = cp.PrescriptionID
  left outer join [ArmadaRX].common.Patient p on p.patientID = a.PatientID
  left outer join [ArmadaRX].aspn.Program prg on prg.ProgramID = a.ProgramID
  left outer join ArmadaApproveRx.dbo.vMember m on m.MemberID = a.FillingPharmacyID
  left outer join ArmadaApproveRx.dbo.vMember m2 on m2.MemberID = a.ReferringPharmacyID

where a.ProgramID in (31)
order by pe.AspnRxID

DROP TABLE #TempTable

end