我需要提高SSRS使用的存储过程的性能。当传递一组非常窄的参数时,存储过程会很快完成。但是当返回超过十万个结果时,存储过程需要几分钟才能运行。
例如,如果我使用1982年到2020年的日期范围运行它,则需要15分钟才能运行并返回180000条记录。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[uspContractFundingbyYear2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[uspContractFundingbyYear2]
GO
-- =============================================
-- Author: J. Dickens
-- Create date: April 2011
-- Description: This SP generates contract funding records for the selected parameters.
-- Each row should represent a single contract funding record.
-- In many cases, either 0 or 100 is used to designate an option that is not selected. The parameter should have no impact on the query.
-- Otherwise all values are passed to the parameter using the multivalue parameter function.
-- =============================================
CREATE PROCEDURE [dbo].[uspContractFundingbyYear2]
@StartYear datetime
,@EndYear datetime
,@BusinessEntityID nvarchar(max)
,@ContractTypeCode nvarchar(max)
,@ContractStatusCode nvarchar(max)
,@ContractOrgID nvarchar(max)
,@ResearchTypeCode nvarchar(max)
,@ExportControlLevelCode nvarchar(max)
,@ScienceAreaID nvarchar(max)
,@ThrustAreaID nvarchar (max)
,@ContractStartdate datetime
,@ContractEnddate datetime
,@ResearchBusID int
,@MasterContractOnlyFlag bit
,@StateProvinceCode nvarchar(max)
,@CountryID nvarchar(max)
,@FinalYearFlag int
,@CollaborativeDollars int
,@SubcontractsFlag int
,@FundingOrgID nvarchar(max)
,@FundingTypeCode nvarchar(max)
,@FundingStatusCode nvarchar(max)
,@FundingStartdate datetime
,@FundingEnddate datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--- Prepare a table of Year Numbers, for use with Cross Join
DECLARE @Dates TABLE (YearNo INT)
;WITH n(n) AS
(
SELECT YEAR(@StartYear)
UNION ALL
SELECT n+1
FROM n
WHERE n < YEAR(@EndYear)
)
INSERT INTO @Dates(YearNo)
SELECT n
FROM n
ORDER BY n
-- Now find all the contract funding records
select distinct
be.BusinessEntityName
, Q.ScienceArea
, r.ResearchBusID
, c.FormattedBusID
, o.Abbreviation as 'ContractOrg'
, c.StateProvinceCode
, cy.CountryName
, cf.ContractFundingID
, c.ContractTypeCode
, c.ContractID,
, [Thrust] = dbo.ufConcatenateThrustsforResTaskDate (r.ResearchID, NULL, NULL, NULL)
, [PI] = (select STUFF((select distinct(coalesce('; '+P.lastfirst,''))
from ResTaskParticipant rtp
join PersonOrg po on rtp.PersonOrgID = po.PersonOrgID
join Person p on po.PersonID = p.PersonID
where rtp.ResearchID = r.researchid
and rtp.ParticipantTypeCode = 'PI'
and (rtp.enddate > getdate() or rtp.enddate = r.enddate)
for XML path ('')),1,2,'')),
c.ContractStatusCode,
cf.Fundingstatuscode as 'FundingStatus', cf.FundingTypeCode as 'FundingType', cf.Funding,
o2.Abbreviation as 'FundingSourceOrg', cf.StartDate, cf.EndDate,
DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate)) as 'ContractMonths', --using 2 days here to allow for leap years
[BurnRate] =
case
when DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate)) = 0 --using 2 days here to allow for leap years
then convert(decimal(2,1), 0)
else
convert(decimal (15,5), convert(decimal(15,0),cf.Funding)/convert(decimal(2,0),(DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate))))) --using 2 days here to allow for leap years
end
, [IsFirstOfMonth] =
case when cf.startdate = (select FirstDayofMonth from dbo.ufGetFirstLastDayofMonth(cf.StartDate, 0)) then 1 else 0 end
, [IsEndOfMonth] =
case when datepart(day,cf.EndDate) = datepart(day,(select LastDayofMonth from dbo.ufGetFirstLastDayofMonth(cf.EndDate, 0))) then 1 else 0 end
, [MonthsInYear] = Convert(decimal(2,0), (select dbo.ufmonthsincontractforyear (cf.startdate, cf.EndDate, d.YearNo)))
,[YearNo] = d.YearNo
from ContractFunding cf
join Contract c on cf.ContractID = c.ContractID
join Research r on c.ResearchID = r.ResearchID
join BusinessEntity be on r.BusinessEntityID = be.BusinessEntityID
join Organization o on c.OrganizationID = o.OrganizationID --Contract Org
join Country cy on c.CountryID = cy.CountryID
join Organization o2 on cf.SourceOrganizationID = o2.OrganizationID --Funding Org
left outer join TaskFunding tf on cf.ContractFundingID = tf.ContractFundingID
--Get the range of years for each Contract Funding row
cross join @Dates d
--get Science Area
cross apply (select [ScienceArea] = dbo.ufConcatenateScienceAreasforResTaskDate (r.ResearchID, NULL, NULL, NULL)) as Q
where
-- required parameters for running report are Start and End Years
cf.StartDate <= @EndYear and cf.EndDate >= @StartYear
-- now all the bells and whistles
and r.BusinessEntityID in (select val from [dbo].[ufStringToTable] (@BusinessEntityID,',',1))
and c.ContractTypeCode in (select val from [dbo].[ufStringToTable] (@ContractTypeCode,',',1))
and c.ContractStatusCode in (select val from [dbo].[ufStringToTable] (@ContractStatusCode,',',1))
and c.OrganizationID in (select val from dbo.ufStringToTable (@ContractOrgID,',',1))
and (@ResearchTypeCode = '0' or (r.ResearchTypeCode in (select val from dbo.ufStringToTable (@ResearchTypeCode,',',1))))
and (@ExportControlLevelCode = '100' or c.ExportControlLevelCode = @ExportControlLevelCode)
-- For Science Area Funding, of the set of Contract Funding records returned, select those that match the given Science Area
and (@ScienceAreaID = '0' or (cf.ScienceAreaID in (select val from dbo.ufStringToTable (@ScienceAreaID,',',1))))
-- For Thrust Area Funding, of the set of Contract Funding records returned, select those that match the given Thrust Area
and (@ThrustAreaID = '0' or (tf.ThrustAreaID in (select val from dbo.ufStringToTable (@ThrustAreaID,',',1))))
-- Find Contracts within given "Active" dates
and (
(@ContractStartdate is null and @ContractEnddate is null)
OR
(c.enddate > @ContractStartdate and c.StartDate <=@ContractEnddate)
or
(@ContractStartdate is null and c.StartDate <=@ContractEnddate)
or
(c.EndDate > @ContractStartdate and @ContractEnddate is null)
)
and (@ResearchBusID = '' or r.ResearchBusID = @ResearchBusID)
and (@MasterContractOnlyFlag = 0 or (@MasterContractOnlyFlag = 1 and c.MasterContractFlag = 1))
and (@StateProvinceCode = '0' or (c.StateProvinceCode in (select val from dbo.ufStringToTable (@StateProvinceCode,',',1))))
and c.CountryID in (select val from dbo.ufStringToTable (@CountryID,',',1)) --Not all contracts have a country assignment
and (@FinalYearFlag = 100
or
(@FinalYearFlag = 0 and (dbo.ufContractIsInFinalYear(c.contractid,getdate()) = 0))
or
(@FinalYearFlag = 1 and (dbo.ufContractIsInFinalYear(c.contractid,GETDATE()) = 1))
)
and (@CollaborativeDollars = 100
or
(@CollaborativeDollars = 0 and
not exists
(select * from ContractFunding cf2 where cf2.FundingTypeCode='Collaborative' and cf2.ContractID=c.ContractID)
)
or
(@CollaborativeDollars = 1 and
exists
(select * from ContractFunding cf2 where cf2.FundingTypeCode='Collaborative' and cf2.ContractID=c.ContractID)
)
)
and (@SubcontractsFlag = 100
or
(@SubcontractsFlag = 0 and c.SubContractFlag = 0)
or
(@SubcontractsFlag = 1 and c.SubContractFlag = 1)
)
and (cf.SourceOrganizationID in (select val from dbo.ufStringToTable (@FundingOrgID,',',1)))
and (cf.FundingTypeCode in (select val from dbo.ufStringToTable (@FundingTypeCode,',',1)))
and (cf.FundingStatusCode in (select val from dbo.ufStringToTable (@FundingStatusCode,',',1)))
and (
(@FundingStartdate is null and @FundingEnddate is null)
OR
(c.enddate > @FundingStartdate and c.StartDate <=@FundingEnddate)
or
(@FundingStartdate is null and c.StartDate <=@FundingEnddate)
or
(c.EndDate > @FundingStartdate and @FundingEnddate is null)
)
End
GO