请在下面检查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
答案 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