【问题标题】:SQL Server - Stored Procedure query performanceSQL Server - 存储过程查询性能
【发布时间】:2015-04-18 16:37:39
【问题描述】:

我需要一些 dDatabase 开发方面的帮助。

我的主表中有 200 万条记录。我的存储过程在视图上运行,视图检索大约 100 万条记录。我的存储过程获得 309 条记录。

我们仅在 2 天前获得了这些数据,我的存储过程需要 25 秒 - 1 分钟来检索记录,直到昨晚,突然之间似乎需要大约 25 分钟才能获得结果,从那时起。

服务器上的 RAM 已增加,以查看这是否会提高性能,但这没有影响。以下是我的基本查询。有人可以调查一下,让我知道如何提高性能。

DECLARE @ReportStartDate DATETIME,
        @ReportEndDate DATETIME, 
        @IsInternalUser INT, 
        @UserId INT, 
        @FFY INT

SET @UserId = 2
SET @FFY = -1
SET @Quarter = -1

/*  Checks if the user is a Internal user or external user */
SELECT @IsInternalUser = rpt.ufn_IsInternalUser(@UserId)

/*Get reporting dates */
SELECT 
    @ReportStartDate = (CASE WHEN MIN(FromDate) >= GETDATE() 
                               THEN GETDATE() 
                               ELSE MIN(FromDate) END), 
    @ReportEndDate = (CASE WHEN MAX(ToDate) >= GETDATE() 
                             THEN GETDATE() 
                             ELSE MAX(ToDate) END) 
FROM 
    rpt.FFYDate      
WHERE 
    FFY = (CASE WHEN @FFY = -1 THEN FFY ELSE @FFY END) 
    AND QuarterNumber = (CASE WHEN @Quarter = -1 THEN QuarterNumber ELSE @Quarter END)

/*Final Query*/
SELECT 
    LC.AwardIdentifier, LC.ProgramName, LC.AwardStartDate, 
    LC.AwardEndDate,
    COUNT(DISTINCT LC.ClientID), LC.RecipientName, LC.ServiceTarget,
    (CASE 
       WHEN (@ReportStartDate >= LC.AwardStartDate AND @ReportEndDate <= LC.AwardEndDate) THEN ((DATEDIFF(MONTH, @ReportStartDate, @ReportEndDate)) * LC.ServiceTarget / (DATEDIFF(Month, LC.AwardStartDate, LC.AwardEndDate))) --WITHIN AWARD DATES                    
       WHEN (@ReportStartDate <= LC.AwardStartDate AND @ReportEndDate <= LC.AwardEndDate) THEN ((DATEDIFF(MONTH, LC.AwardStartDate, @ReportEndDate))  * LC.ServiceTarget / (DATEDIFF(Month, LC.AwardStartDate, LC.AwardEndDate))) --OVERLAP WITH AWARD DATES                    
       ELSE 0
    END) AS ClientTarget
FROM    
    rpt.VwCSATIntakeCoverageReport_Legacy LC
LEFT JOIN 
    UserRoleEntity URE ON URE.EntityId = (CASE WHEN ure.EntityTypeCode = 'AWARD' THEN LC.AwardID WHEN ure.EntityTypeCode ='SITEAWARD' THEN LC.SiteAwardId END) 
LEFT JOIN 
    CDPUserRole UR ON URE.UserRoleId = UR.Id AND UR.CDPUserId = @UserId
WHERE 
    (LC.InterviewDate BETWEEN @ReportStartDate AND @ReportEndDate) 
    AND (@IsInternalUser = 1 -- Interanl User
         OR (UR.CDPUserId = @UserId AND UR.ID IS NOT NULL)) -- External User
GROUP BY 
    LC.AwardIdentifier, LC.ProgramName, LC.AwardStartDate, 
    LC.AwardEndDate, LC.RecipientName, LC.ServiceTarget

我的技术主管对此进行了调查,并说问题可能出在 COUNT(DISTINCT LC.ClientID) 和由此产生的 group by 上,并要求我对此发表评论(并在顶部选择中添加“不同”。我尝试添加 @987654323 @ 声明在我的最终选择查询之上,并尝试在顶部执行COUNT(DISTINCT LC.ClientID),但性能没有改变。

这需要在本周投入生产,任何帮助将不胜感激!谢谢!

【问题讨论】:

  • 执行计划的瓶颈是什么?
  • 我可能会研究参数嗅探。缓存的查询计划对于您现在正在运行的内容可能很糟糕。表上有哪些索引(如果有)?

标签: sql sql-server performance stored-procedures


【解决方案1】:

首先,对存储过程运行查询执行计划。查找任何单词,而不是扫描而不是查找。此外,查询执行计划应该推荐任何缺失的索引。完成此操作后,将其添加到代码顶部以获取更多信息:

SET STATISTICS IO ON
SET STATISTICS TIME ON

这将向您显示在查询中访问每个表的成本,并且您可以确定您的哪个表正在减慢您的速度。

至于 COUNT(DISTINCT fieldname) ,您可以尝试使用 CTE 来获取您想要的特定 ClientID 池并在 ClientID 上内部加入 CTE,然后计算该数字。运行查询执行计划并查看统计信息并告诉我您发现了什么。

【讨论】:

  • 我运行了这个。但我不知道如何解码这些信息。
  • SET SHOWPLAN_ALL ON GO SET FMTONLY ON SET STATISTICS IO ON SET STATISTICS TIME ON EXEC @return_value = [rpt].[usp_IntakeCoverageReport] SET FMTONLY OFF GO SET SHOWPLAN_ALL OFF GO
  • 您正在寻找较大的 IO 数。如果表正在对超过 500,000 -1,000,000 IO 进行堆扫描或逻辑扫描,则可能存在性能问题。查询执行选项卡是否建议了任何索引?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
相关资源
最近更新 更多