Да, это странно.
У нас есть веб-сервис, который возвращает данные клиенту Silverlight. Запросы генерируются для базы данных SQL Server 2008 с использованием структуры сущностей. Большинство этих запросов основаны на диапазоне дат - например, извлекайте результаты между этой датой и той. Кроме того, представление используется для облегчения работы.
Мы заметили, что при выдаче определенного набора запросов, которые начинаются в или после определенной даты, выполнение будет очень медленным. Эта дата 5 ноября любого года. Если наша дата начала на один день раньше, исполнение будет мгновенным. Итак, 5-6, медленный. 4-6 - быстрый.
Вот SQL, который генерирует EF:
ЭТОТ ЗАПРОС БУДЕТ ОЧЕНЬ МЕДЛЕННЫМ (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]
Если мы установим дату начала 5 ноября прошлого года, выполнение будет медленным, 4 ноября прошлого года и снова быстрым. Глядя на данные в базе данных нет ничего необычного вокруг 5-го. Кроме того, кажется, что запросы с датой начала после 5-го числа будут выполняться медленно.
Я в тупике!
(база данных размещена удаленно, поэтому у меня нет прямого доступа к ней)
UPDATE
Спасибо за ответ, ребята. Во-первых, я, вероятно, должен прояснить, что мои знания о сервере sql очень важны. Я создаю базы данных разного качества, а затем использую что-то вроде Linq To SQL или EF для работы с ними. Так что я чувствую себя немного не в своей тарелке.
Относительно объединений - представление, которое я запрашиваю, включает данные из 6-7 таблиц. В следующий раз я постараюсь взять статистику на работе и добавить здесь дополнительную информацию. Я не очень много знаю о планах выполнения, или я вижу их в SQL Server Management Studio
UPDATE
Статистика из медленного запроса
(Затронуты 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.
UPDATE
План выполнения запроса (для меня новость) предполагает добавление нового индекса в строку в одной из таблиц - 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 и структуру синхронизации. Поэтому я всегда беспокоился о том, что изменения в базе данных повлияют на отслеживаемые данные и сломают вещи для моих клиентов. Будет ли добавление данных отслеживания изменений сброса индекса?
Спасибо за вашу помощь, ребята. Я чувствую себя полным новичком здесь.