Необходимо повысить производительность SQL-запросов с помощью агрегатных функций - PullRequest
7 голосов
/ 15 августа 2011

У меня есть определенный запрос SQL, который, похоже, страдает от загадочной проблемы с производительностью.Вот запрос:

SELECT COUNT(LengthOfTime) AS TotalTime, 
       SUM(LengthOfTime) AS TotalLength, 
       SUM(LengthOfTime) / COUNT(LengthOfTime) AS AverageTime, 
       SUM(Pops) / COUNT(LengthOfTime) AS AveragePop 
  FROM ((SELECT * 
           FROM (SELECT *, ID & YearRec AS ID2 
                   FROM MyFirstTable 
                 UNION ALL 
                 SELECT *, ID & YearRec AS ID2 
                   FROM Table2011) AS TEMP 
          WHERE STARTTIME >= '8/1/2011 00:00:00' 
            AND StartTime <= '8/5/2011 23:59:59' ) AS TEMP2 
  JOIN AppleTable ON TEMP2.Reason = AppleTable.Skills ) 
  JOIN PeopleTable ON TEMP2.Operator = PeopleTable.Operators 
 WHERE AppleTable.[ON] = 1 
   AND PeopleTable.[ON] = 1 
   AND Rec_Type = 'SECRET AGENT'

Проблема в том, что этот запрос выполняется очень быстро (от 0:00 до 0:02) при выполнении в течение 5 дней, но очень медленно (от 1:20 до 145) на 6 дней.

В таблицах содержится приблизительно 105 000 записей в день (MyFirstTable и Table2011).

Мой вопрос : Существует ли верхний предел количества строк, которые вы можете передать статистической функции, прежде чем вы увидите серьезную проблему производительности в SQL Server?(в настоящее время используется 2008 R2)

Ответы [ 2 ]

9 голосов
/ 15 августа 2011

Краткий ответ: Нет, не существует какого-то волшебного количества записей, из-за которых MSSQL начинает плохо работать.

Теперь, возможно, запросы будут плохо масштабироваться и, как результат, чем больше набор данныхчем [экспоненциально] он хуже работает.

Большая проблема, с которой вы столкнетесь, заключается в том, что вы прогнозируете StartTime после операторов UNIONED.Вместо этого, попробуйте предсказать это в обоих ваших избранных до UNION.Это должно иметь огромное значение, особенно если вы индексируете обе таблицы в StartTime (создание индекса ищет по этим таблицам).

SELECT * FROM (
SELECT *, ID & YearRec AS ID2 FROM MyFirstTable 
   WHERE STARTTIME >= '8/1/2011 00:00:00' 
   AND STARTTIME <= '8/5/2011 23:59:59'
UNION ALL SELECT *, ID & YearRec AS ID2 
FROM Table2011
   WHERE STARTTIME >= '8/1/2011 00:00:00' 
   AND STARTTIME <= '8/5/2011 23:59:59'
) AS TEMP 

Возможно, вы также сможете выполнить некоторый дополнительный рефакторинг вашего кода.

4 голосов
/ 15 августа 2011

Нет, предварительно установленный верхний предел для агрегатных функций.

На производительность, вероятно, влияет одно или несколько из следующих значений:

  • Старая и / или неподходящая структура индекса
  • Кэшированный план выполнения
  • Кэшированные данные
  • размер данных не одинаков (первые пять дней - 10 строк, а шестая - 100 строк)

Вы можете выполнить запрос в SSMS и просмотреть фактический план выполнения. Это скажет вам места, где стоимость выполнения запроса является самой высокой, и это поможет вам определить лучший курс действий.

Редактировать на основе комментариев:

Если в Table2011 отсутствует индекс, содержащий [STARTTIME], создайте его. Если есть индекс, но он игнорируется, то вам нужно выяснить, почему. Если фрагментация фрагментирована, то перестройка индекса определенно поможет. Вот как восстановить

ALTER INDEX [YourIndexName] ON [dbo].[Table2011] REBUILD WITH (STATISTICS_NORECOMPUTE = ON);

В качестве альтернативы вы можете сделать это в SSMS - перейдите к определенному индексу в браузере объектов, щелкните правой кнопкой мыши и перестройте.

...