没错,这很奇怪。
我们有一个将数据返回给 silverlight 客户端的网络服务。使用 Entity Framework 针对 SQL Server 2008 数据库生成查询。大多数这些查询都是基于日期范围的——例如,在这个日期和那个日期之间提取结果。此外, View 用于使事情变得更容易一些。
我们注意到,当发出一组在特定日期或之后开始的特定查询时,执行速度会非常慢。这个日期是每年的 11 月 5 日。如果我们的开始日期早一天,执行将是即时的。所以,第 5 到第 6,慢。第 4 - 6 - 快。
这是 EF 生成的 SQL:
这个查询会非常慢(30 秒)
SELECT
1 AS [C1],
[GroupBy1].[K1] AS [Name],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[Name] AS [K1],
SUM([Extent1].[Value]) AS [A1]
FROM (SELECT
[view_answers].[Value] AS [Value],
[view_answers].[Comment] AS [Comment],
[view_answers].[NewStockist] AS [NewStockist],
[view_answers].[NewDistPoint] AS [NewDistPoint],
[view_answers].[VoucherUsed] AS [VoucherUsed],
[view_answers].[CashTotal] AS [CashTotal],
[view_answers].[AnswerType] AS [AnswerType],
[view_answers].[StartTime] AS [StartTime],
[view_answers].[ActualEndTime] AS [ActualEndTime],
[view_answers].[Complete] AS [Complete],
[view_answers].[UserID] AS [UserID],
[view_answers].[UserName] AS [UserName],
[view_answers].[QuestionType] AS [QuestionType],
[view_answers].[ProductSKU] AS [ProductSKU],
[view_answers].[BrandID] AS [BrandID],
[view_answers].[TeamID] AS [TeamID],
[view_answers].[Name] AS [Name],
[view_answers].[Stage] AS [Stage],
[view_answers].[Question] AS [Question]
FROM [dbo].[view_answers] AS [view_answers]) AS [Extent1]
WHERE
([Extent1].[UserID] = '16E3692F-806E-40A0-BB99-ABBBCC13060D')
AND (N'Distribution Points' = [Extent1].[QuestionType])
AND ([Extent1].[StartTime] >= '11/05/2009 00:00:00')
AND ([Extent1].[StartTime] <= '11/08/2009 00:00:00')
AND (1 = [Extent1].[Complete])
AND (2 = [Extent1].[BrandID])
AND (N'Distribution Points' = [Extent1].[QuestionType])
GROUP BY
[Extent1].[Name])
AS [GroupBy1]
这个会快得多
SELECT
1 AS [C1],
[GroupBy1].[K1] AS [Name],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[Name] AS [K1],
SUM([Extent1].[Value]) AS [A1]
FROM (SELECT
[view_answers].[Value] AS [Value],
[view_answers].[Comment] AS [Comment],
[view_answers].[NewStockist] AS [NewStockist],
[view_answers].[NewDistPoint] AS [NewDistPoint],
[view_answers].[VoucherUsed] AS [VoucherUsed],
[view_answers].[CashTotal] AS [CashTotal],
[view_answers].[AnswerType] AS [AnswerType],
[view_answers].[StartTime] AS [StartTime],
[view_answers].[ActualEndTime] AS [ActualEndTime],
[view_answers].[Complete] AS [Complete],
[view_answers].[UserID] AS [UserID],
[view_answers].[UserName] AS [UserName],
[view_answers].[QuestionType] AS [QuestionType],
[view_answers].[ProductSKU] AS [ProductSKU],
[view_answers].[BrandID] AS [BrandID],
[view_answers].[TeamID] AS [TeamID],
[view_answers].[Name] AS [Name],
[view_answers].[Stage] AS [Stage],
[view_answers].[Question] AS [Question]
FROM [dbo].[view_answers] AS [view_answers]) AS [Extent1]
WHERE
([Extent1].[UserID] = '16E3692F-806E-40A0-BB99-ABBBCC13060D')
AND (N'Distribution Points' = [Extent1].[QuestionType])
AND ([Extent1].[StartTime] >= '11/04/2009 00:00:00')
AND ([Extent1].[StartTime] <= '11/08/2009 00:00:00')
AND (1 = [Extent1].[Complete])
AND (2 = [Extent1].[BrandID])
AND (N'Distribution Points' = [Extent1].[QuestionType])
GROUP BY
[Extent1].[Name])
AS [GroupBy1]
如果我们将开始日期设置为去年 11 月 5 日,执行会很慢,去年 11 月 4 日,然后又很快。查看数据库中的数据,5号左右没有异常。此外,开始日期在 5 号之后的查询似乎运行缓慢。
我被难住了!
(数据库是远程托管的,所以我不能直接访问它)
更新
谢谢大家的回复。首先,我可能应该明确表示我对 sql server 的了解很肤浅。我构建了不同质量等级的数据库,然后使用 Linq To SQL 或 EF 之类的工具来处理它们。所以我在这里感觉有点力不从心。
关于连接——我正在查询的 View 确实包含来自大约 6-7 个表的数据。下次工作时,我将尝试获取一些统计数据,并在此处添加更多信息。我不太了解执行计划,或者它们是我可以通过 SQL Server Management Studio 看到的东西
更新 来自慢查询的统计 (3 行受影响)
Table 'tblProducts'. Scan count 0, logical reads 22, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblQuestionTypes'. Scan count 0, logical reads 1496, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblQuestions'. Scan count 0, logical reads 1496, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblSessions'. Scan count 0, logical reads 28551, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblAnswers'. Scan count 1, logical reads 1976256, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblCalls'. Scan count 1, logical reads 439, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblUsers'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
快速查询统计
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblAnswers'. Scan count 1, logical reads 7008, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblProducts'. Scan count 0, logical reads 22, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblQuestions'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblQuestionTypes'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblCalls'. Scan count 1, logical reads 439, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblSessions'. Scan count 1, logical reads 47, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblUsers'. Scan count 0, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
更新 查询执行计划(对我来说是新事物)建议我向其中一个表中的行添加一个新索引 - answers 表中的 questionid。建议的sql如下:
USE [brandfourcoke]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[tblAnswers] ([QuestionID])
INCLUDE ([CallID],[Value])
GO
查询成本的估计改进为 93%。 我应该继续这样做吗?该数据库处于实时环境中,并使用 sql server 2008 的更改跟踪和同步框架。因此,我一直担心数据库更改会影响跟踪数据并破坏我的客户。添加索引重置会更改跟踪数据吗? 谢谢大家的帮助。我觉得自己在这里完全是个初学者。
最佳答案
使用 SET sTATISTICS IO ON
运行慢速和快速查询,看看两者之间的逻辑读取/物理读取量是否存在显着差异。
数据很可能存在严重偏差。例如,快速计划执行由 10 行结果驱动的嵌套循环(导致 10 次嵌套查找),而慢速计划突然看到 10000 行,而前一个计划看到 10 行,导致 10000 次查找。尽管您的查询没有连接,但引擎可能会使用各种访问索引并将索引与集群索引连接起来。实际的执行计划总是会准确地揭示正在发生的事情。
关于sql-server - SQL 服务器 2008 : Very slow query performance when dealing with specific date boundary,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1743679/