c# - 生成报告时缩短执行时间

c# - Improve execution time when generating report

我在 visual studio 2010 年有一个程序,其中我有一个生成报告到 crystal 报告的功能。查询是在我的一个存储过程中提供的,用于从我的数据库中检索信息。

我在点击生成报告时遇到的问题,return 结果需要很长时间。我想知道是否有人建议如何通过优化存储过程中的查询来更快地缩短执行时间?

这是存储过程的一个片段:

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[M_RPT_DailyIssuedVoucher]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'ALTER PROCEDURE [dbo].[M_RPT_DailyIssuedVoucher]
    @EventCode [varchar](8),
    @LocID [varchar](10),
    @Status [char](2),
    @DtFrom [datetime],
    @DtTo [datetime],
    @IssuedBy [nvarchar](128)
WITH EXECUTE AS CALLER
AS
SET NOCOUNT ON


Select SerialNo,
         CardID,
         CardHolder AS [Name],
         CardType,
         EventCode,
         IssueDate, 
         IssueBy,
         ValidFromDate,
         ValidToDate,
         IssueLocationID,
         IssueComputerName,
         ManualIssueReason, 
         [Status],
         Remarks,
         CancelReason
/*      '' CollectedStatus ='' +
            '' CASE''+ 
                '' WHEN LTRIM(RTRIM(CollectBy))<>'''''''' THEN ''''Y''''''+
                '' ELSE ''''N''''''+
            '' END'' +
*/
    FROM IssuedVoucher with (nolock)
    WHERE 
(@EventCode = '''' OR (EventCode = @EventCode))
And(@IssuedBy = '''' OR (IssueBy= @IssuedBy))
AND (@LocID = '''' OR (IssueLocationID = @LocID))
AND (@Status = '''' OR (Status = @Status))
AND(@DtFrom IS NULL OR IssueDate >= @DtFrom )
AND (@DtTo IS NULL OR IssueDate <= @DtTo)

 ORDER BY SerialNo, EventCode

这里是创建 table for issuedvoucher 的查询:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[IssuedVoucher](
    [BatchNo] [decimal](18, 0) NOT NULL,
    [SerialNo] [varchar](15) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [ManualIssueReason] [varchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [IssueLocationId] [varchar](8) COLLATE Latin1_General_CI_AS NULL,
    [IssueComputerName] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [Remarks] [varchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CardId] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CardHolder] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CardType] [varchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [EventCode] [varchar](8) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [PromotionBenefitCode] [varchar](8) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [ValidFromDate] [datetime] NOT NULL,
    [ValidToDate] [datetime] NOT NULL,
    [VisiblePoint] [decimal](18, 2) NOT NULL,
    [HiddenPoint] [decimal](18, 2) NOT NULL,
    [LoyaltyPoint] [decimal](18, 2) NOT NULL,
    [NNECash] [decimal](18, 0) NULL,
    [Status] [char](2) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [PrintStatus] [char](2) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [IssueDate] [datetime] NOT NULL,
    [IssueBy] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CollectDate] [datetime] NOT NULL,
    [CollectBY] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CollectLocationId] [varchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [CancelReason] [varchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [LastChangeBy] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [LastChangeDate] [datetime] NOT NULL,
    [RecordVersion] [timestamp] NOT NULL,
    [AllotmentID] [decimal](18, 0) NOT NULL,
    [GuestType] [bit] NOT NULL,
    [CompanyID] [bigint] NULL,
    [DepartmentID] [smallint] NULL,
    [IDIssuedCountry] [nvarchar](50) COLLATE Latin1_General_CI_AS NULL,
    [EVoucherBatchNo] [decimal](18, 0) NULL,
    [EVoucherGuestNo] [decimal](18, 0) NULL,
    [EVoucherSerialNo] [varchar](50) COLLATE Latin1_General_CI_AS NULL,
    [Barcode] [varchar](50) COLLATE Latin1_General_CI_AS NULL,
    [Monetary] [bit] NOT NULL,
    [Discount] [bit] NOT NULL,
    [ConsiderationValue] [decimal](18, 2) NULL,
    [FaceValue] [decimal](18, 0) NULL,
    [IntercoRate] [decimal](18, 0) NULL,
    [SAPCostCentre] [varchar](10) COLLATE Latin1_General_CI_AS NULL,
    [SAPIONumber] [varchar](25) COLLATE Latin1_General_CI_AS NULL,
    [IsGift] [bit] NOT NULL,
    [PrintCount] [int] NOT NULL,
    [TaxInvoiceID] [decimal](18, 0) NULL,
    [IdentificationNumber] [varchar](50) COLLATE Latin1_General_CI_AS NULL,
    [IdentificationType] [varchar](5) COLLATE Latin1_General_CI_AS NULL,
    [CRMEntitlementMasterID] [nvarchar](20) COLLATE Latin1_General_CI_AS NULL,
    [DeductPointType] [smallint] NULL,
    [DeductCreditType] [smallint] NULL,
    [AwardPointType] [smallint] NULL,
    [AwardCreditType] [smallint] NULL,
    [AwardCreditValue] [decimal](18, 2) NULL,
    [deductPointvalue] [decimal](18, 2) NULL,
    [deductCreditvalue] [decimal](18, 2) NULL,
    [AwardPointvalue] [decimal](18, 2) NULL,
 CONSTRAINT [PK_IssuedVoucher2] PRIMARY KEY CLUSTERED 
(
    [SerialNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
END
GO
/****** Object:  Index [_dta_index_IssuedVoucher_18_1736445310__K1]    Script Date: 04/12/2017 3:39:19 PM ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND name = N'_dta_index_IssuedVoucher_18_1736445310__K1')
CREATE NONCLUSTERED INDEX [_dta_index_IssuedVoucher_18_1736445310__K1] ON [dbo].[IssuedVoucher]
(
    [BatchNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 80) ON [PRIMARY]
GO

SET ANSI_PADDING ON
GO

/****** Object:  Index [_dta_index_IssuedVoucher_18_1736445310__K2_K10_7_25_55]    Script Date: 04/12/2017 3:39:19 PM ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND name = N'_dta_index_IssuedVoucher_18_1736445310__K2_K10_7_25_55')
CREATE NONCLUSTERED INDEX [_dta_index_IssuedVoucher_18_1736445310__K2_K10_7_25_55] ON [dbo].[IssuedVoucher]
(
    [SerialNo] ASC,
    [EventCode] ASC
)
INCLUDE (   [CardId],
    [CancelReason],
    [IdentificationNumber]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 80) ON [PRIMARY]
GO

SET ANSI_PADDING ON
GO

/****** Object:  Index [idx_CardID]    Script Date: 04/12/2017 3:39:19 PM ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND name = N'idx_CardID')
CREATE NONCLUSTERED INDEX [idx_CardID] ON [dbo].[IssuedVoucher]
(
    [BatchNo] ASC,
    [CardId] ASC,
    [Status] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 80) ON [PRIMARY]
GO

SET ANSI_PADDING ON
GO

/****** Object:  Index [IX_IssuedVoucher_1]    Script Date: 04/12/2017 3:39:19 PM ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND name = N'IX_IssuedVoucher_1')
CREATE NONCLUSTERED INDEX [IX_IssuedVoucher_1] ON [dbo].[IssuedVoucher]
(
    [CardId] ASC,
    [CardType] ASC,
    [EventCode] ASC,
    [PromotionBenefitCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = ON, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 80) ON [PRIMARY]
GO

SET ANSI_PADDING ON
GO

/****** Object:  Index [RecordVoucher]    Script Date: 04/12/2017 3:39:19 PM ******/
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[IssuedVoucher]') AND name = N'RecordVoucher')
CREATE NONCLUSTERED INDEX [RecordVoucher] ON [dbo].[IssuedVoucher]
(
    [EVoucherSerialNo] ASC,
    [Barcode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY]
GO

根据我的经验,WHERE 运算符可能是问题所在。我有一个类似的问题,不是报告引擎,而是从数据库访问信息。 Imo,IS NULL 正在降低性能。不过我可能是错的,因为我不是数据库专家。 我通过排除 IS NULL 语句解决了我的问题。获得数据集合后,我在 C# 中生成了一个新集合,其中包含此类语句。

首先,为什么你每次都改变 proc 我不明白?

您可以简单地从您的代码中调用 proc 并仅将 Select 向前放入动态 Sql.

您可以在此 manner.If 中修改您的内部 select 查询 您的 table 是很好的索引然后它可以利用索引。

             declare @EventCode [varchar](8)
   declare @LocID [varchar](10)
   declare @Status [char](2)
   declare @DtFrom [datetime]
   declare @DtTo [datetime]
   declare @IssuedBy [nvarchar](128)
   declare @SqlCondtion nvarchar(max)=''

   DECLARE @ParmDefinition nvarchar(500);  
    SET @ParmDefinition = N'@EventCode1 [varchar](8) 
                            , @LocID1 [varchar](10) 
                            , @Status1 [char](2)
                            , @DtFrom1 [datetime] 
                            ,@DtTo1 [datetime]
                            ,@IssuedBy1 [nvarchar](128)';  

declare @Sql nvarchar(max)=N'Select SerialNo,
         CardID,
         CardHolder AS [Name],
         CardType,
         EventCode,
         IssueDate, 
         IssueBy,
         ValidFromDate,
         ValidToDate,
         IssueLocationID,
         IssueComputerName,
         ManualIssueReason, 
         [Status],
         Remarks,
         CancelReason
    FROM IssuedVoucher with (nolock)
    WHERE 1=1 ' 

if(@EventCode is not null) 
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and EventCode = @EventCode1 '

if(@IssuedBy is not null)
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and IssueBy = @IssuedBy1 '


if(@LocID is not null  )
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and IssueLocationID = @LocID1 '

if(@Status is not null )
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and [Status] = @Status1 '

if(@DtFrom is not null )
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and [IssueDate] >= @DtFrom1 '

if(@DtTo is not null )
set @SqlCondtion=@SqlCondtion+CHAR(10)+ 'and [IssueDate] <= @DtTo1 '

set @Sql=@Sql+CHAR(10)+@SqlCondtion

print @Sql
EXECUTE sp_executesql @Sql, @ParmDefinition, @EventCode1 = @EventCode, @IssuedBy1=@IssuedBy ,@LocID1=@LocID
                                            ,@Status1=@Status,@DtFrom1=@DtFrom,@DtTo1=@DtTo; 

您可以根据您的要求进一步修改此脚本或修复 bug.print 应在调试后进行注释。