Медленный запрос с помощью хранимой процедуры при запросе новых записей - PullRequest
4 голосов
/ 28 марта 2012

Извините за стену текста ниже ...

У меня здесь немного странная проблема. У меня довольно большая таблица, в которой хранятся данные журнала отслеживания сообщений из Exchange 2007 за последние пару дней. Количество записей исчисляется миллионами (около 10–12 миллионов), и каждые 30 минут я массово вставляю новые журналы со всех наших транспортных серверов через запланированные задачи PowerShell.

Один раз за ночь я запускаю задачу обслуживания, чтобы очистить все журналы старше дневного, чтобы таблица не становилась слишком большой, хотя я бы хотел сохранить журналы немного дольше, если смогу.

Таблица называется MessageTracking и имеет первичный ключ, который представляет собой столбец IDENTITY int, [MessagelogID] , который увеличивается на 1 для каждой записи.

Существует некластеризованный индекс для столбца [дата-время] для [дата-время] asc.

В полях Отправитель и Получатель имеется полнотекстовый индекс.

Пользователи могут выполнять поиск в таблице с помощью веб-страницы внешнего интерфейса, которую я написал на C # Asp.net. Страница позволяет выполнять простой поиск в 4 полях поиска:

  • Дата начала, время
  • End DateTime
  • Отправитель
  • Получатель

Это передает запрос хранимой процедуре, которая фактически возвращает записи обратно. хранимая процедура называется GetMessageTracking .

Теперь о моей странной проблеме. Этот запрос возвращает результаты в 0 секунд, молниеносно:

USE [DATABASENAME]
GO

DECLARE @return_value int

EXEC    @return_value = [dbo].[GetMessageTracking]
        @maximumRows = 20,
        @startRowIndex = 0,
        @sortExpression = N'[date-time]',
        @SearchStartDate = N'2012-03-27 13:51',
        @SearchEndDate = N'2012-03-27 20:09',
        @SearchSender = N'user@domain.com',
        @SearchRecipient = N'Default'

SELECT  'Return Value' = @return_value

GO

Если я изменю параметр @SearchStartDate на час, т. Е. N'2012-03-27 14: 51 ', то он не будет завершен в течение очень очень долгого времени.

Я могу только предположить, что у него серьезные проблемы с моим указателем даты и времени, так как полнотекстовый каталог обычно простаивает. Одна из проблем, с которыми я сталкиваюсь, заключается в том, что я буквально вставляю тысячи записей в час, и индекс ( IX_DateTime ) очень быстро фрагментируется, однако я не могу придумать отличный способ остановить это.

Так что мои вопросы действительно в два раза:

1) Как я могу увидеть, что вызывает эту проблему с запросами, занимающими некоторое время при поиске новых записей?

2) Есть ли какие-либо советы по индексированию при большом количестве вставок?

Я подумал, что, может быть, это были планы выполнения, вызывающие это странное поведение, но нет, это кажется нормальным Я попытался добавить опцию WITH RECOMPILE к запросам, и это не имело никакого значения. Я также очистил кэш плана выполнения безрезультатно.

Уверен, мои проблемы полностью связаны с индексацией.

Спасибо!

Ответы [ 3 ]

1 голос
/ 28 марта 2012

Использование перекомпиляции было хорошим первым шагом.Поэтому мы можем исключить вероятность того, что параметр сниффинг, если проблема.

Пожалуйста, опубликуйте скриншот плана выполнения.Я думаю, что проблема станет понятной таким образом.Я думаю, что это проблема статистики.оптимизатор запросов считает, что строк с DateTime> = N'2012-03-27 14:51 'нет, и поэтому выбирает неправильный план.Попробуйте запустить sp_updatestats.

Что касается # 2 ваших вопросов: задайте для отступа индекса какое-то значение в диапазоне 50-80.

0 голосов
/ 31 марта 2012

Я думаю, что вы определили свою собственную проблему - фрагментацию индексов с большим количеством записей, которые вы делаете.

Вы можете помочь решить эту проблему, настроив отступ (дисковое пространство), выделенный для роста.таблицы и индексы.

0 голосов
/ 28 марта 2012

Из-за большого количества INSERT и DELETE возможно, что у вас могут быть фрагментированные индексы в вашей таблице. Следующий скрипт (взят из SQL Authority ) предоставит вам информацию о фрагментации

select object_name(i.object_id) as table_name,
       indexstats.avg_fragmentation_in_percent
from sys.dm_db_index_physical_stats(db_id(), null, null, null, 'detailed') indexstats
inner join sys.indexes i 
   on i.object_id = indexstats.object_id and i.index_id = indexstats.index_id
where indexstats.avg_fragmentation_in_percent > 20

Если вы обнаружите большую фрагментацию, вы можете перестроить или реорганизовать индексы. В SQL Authority есть еще одна статья , в которой содержится следующая информация.

Перестроение индекса: Этот процесс удаляет существующий индекс и воссоздает индекс.

alter index all on schema.table_name rebuild

Реорганизация индекса: Этот процесс физически реорганизует конечные узлы индекса.

alter index all on schema.table_name reorganize
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...