【问题标题】:c# - Improve execution time when generating reportc# - 改进生成报告时的执行时间
【发布时间】:2017-12-04 07:21:29
【问题描述】:

我在 Visual Studio 2010 中有一个程序,我有一个生成水晶报表的功能。该查询是在我的一个存储过程中提供的,用于从我的数据库中检索信息。

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

这是存储过程的sn-p:

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

这是为已发行凭证创建表的查询:

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

【问题讨论】:

  • 你指的是哪一行?
  • EXEC dbo.sp_executesql @statement = N'ALTER PROCEDURE [dbo].[M_RPT_DailyIssuedVoucher]
  • 它一直在那里,所以我可以在生成报告时执行 sp?
  • 你检查过执行计划吗?索引碎片?
  • 那么,执行计划到底是什么?我看不出这些索引对执行此过程有何帮助。

标签: c# sql sql-server visual-studio crystal-reports


【解决方案1】:

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

【讨论】:

  • 那么你认为有什么帮助?
  • IssueDate 是可为空的 DateTime 是否正确?如果我没记错的话,他会检查所有条目,因为 IS NULL。您应该考虑拆分查询 imo。获取所有有效的 IssueDates,然后是所有 null IssueDates 并将它们合并到一个集合中。
  • 顺便说一句,你如何在你的 c# 上下文中访问这个存储过程?实体框架?
  • 我在我的 c# 代码中使用 command.parameters.addwithvalue(存储过程中的参数名称)调用存储过程
  • 小心 c# 中的 AddWithValue 语句。阅读此blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
【解决方案2】:

首先,为什么你每次都改变 proc 对我来说是不可理解的?

您可以简单地从您的代码中调用 proc,然后只在动态 Sql 中添加 Select。

你可以用这种方式修改你的内部选择查询。如果你的表是很好的索引,那么它可能会利用索引。

             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; 

您可以进一步修改此脚本以满足您的要求或修复错误。调试后应注释打印。

【讨论】:

  • @mjwills,在阅读整个答案或理解它之前停止投票。我在我的脚本中使用 Exec (@Sql)。我禁止用户使用 sp_executesql。由于用户已经在使用 sp_executesql 并且我只给出了部分解决方案。Hv 你真的理解我的答案吗?
  • 是的,您的评论很有价值。请等待我的更正,我和 Bob 一起来。
  • 感谢您指出错误。我已经做了很多时间。不知道为什么我错过了这么多事情。可能是我想在这里给出粗略的想法。
  • @mjwills,你走了吗?检查我的答案和最后 2 个 cmets。
  • @mjwills,所以你认为我的逻辑对用户没有帮助?它不会提高性能?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-21
相关资源
最近更新 更多