SQL Server 2014 Внезапное замедление / Нет вставок / Не связано с оборудованием или индексом


8

Я использую 350GBбазу данных на моем компьютере с ~ 40 миллионами строк.

SQL Server 2014, Win7, AMD 8350 @ 4,8 ГГц, 16 ГБ ОЗУ и твердотельный накопитель емкостью 500 ГБ (база данных размещается на собственном твердотельном накопителе емкостью 500 ГБ с пропускной способностью чтения / записи 500 МБ / 500 МБ).

База данных не обновляется, я просто анализирую / читаю ее. На создание нескольких indexes, любых joinи count(*)т. Д. Уходит менее 1 минуты, что вполне подходит для моих целей. Я выполнял некоторые запросы (после выполнения одного запроса на соединение, 40-50 раз, он становится медленным) для данных, и теперь вызовы, которые заняли 1 минуту, все еще выполняются через 20 минут.

Я внимательно слежу за системными ресурсами, и вижу, как SSDзапускается запрос, он читает в течение 20-30 секунд, а затем читает в 121kB/secondтечение следующих 20 минут. Это не проблема процессора или проблема с диском. Я ограничен объемом оперативной памяти, однако при первой загрузке базы данных вызовы выполняются нормально, но через 25 минут ничего не происходит.

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

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

Я пытаюсь подсчитать все экземпляры TypeID за 5 секунд до времени, основанного на таблице ACALLS.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

После запуска «Кто бежит», введите описание изображения здесь введите описание изображения здесь


Я подозреваю, что это связано со статистикой таблиц и типами обработки соединений. Вы должны посмотреть на планы выполнения для запросов: объединение вложенных циклов может быть признаком проблем.
Гордон Линофф

Вы пробовали с RECOMPILE?

3
Опубликовать фактический план выполнения удивительно медленного запроса. Чем проще запрос, тем лучше.
USR

1
Вы обновили статистику по всем таблицам? Вы перестроили все индексы? Информация о sp_whoisactive: ссылки
TT.

2
Эти статистические данные об ожиданиях показывают много операций ввода-вывода, но мы не знаем, какая доля запроса - это операции ввода-вывода и какова загрузка ЦП. Выполните тесты, которые я рекомендовал, как опубликовать результаты.
USR

Ответы:


2

У вас есть запрос без SARGable - даже если у вас хорошие индексы, вы не используете их в этом запросе.

Во-первых, реакция коленного рывка на pageiolatch_sh - это чтение страниц с диска в буфер; у вас недостаточно оперативной памяти для данных, которые он пытается извлечь.

Во-вторых, вам нужно посмотреть на план выполнения и его использование индексов - или их отсутствие.

Прекратите использовать функции в своих объединениях и в своем WHERE и получите только те данные, которые вам абсолютно необходимы для начала.

  • «МЕЖДУ ACALLS.StartTime и DATEADD (ss, -5, ACALLS.StartTime)» - избавиться от этого DATEADD в BETWEEN.

    • Если это база данных отчетов только для чтения, то создайте таблицу отчетов только с необходимыми вам данными, а затем добавьте в нее составные индексы, как требуется. Используйте его, чтобы получить первичные ключи / другие уникальные ключи нужных вам строк ACALLS, а затем получить остальные данные ACALLS.
  • WHERE DATEPART (час, MainView.TimeStamp) между 10 и 13 и CAST (MainView.TimeStamp как дата) = '2015-12-09'

    • то же самое - избавиться от CAST - заменить '2015-12-09' на один или два @параметра правильного типа данных для MainView.TimeStamp> = @StartTimestamp AND MainView.TimeStamp <@EndTimestamp

    • и избавьтесь от этого DATEPART, ограничив @StartTimestamp и @EndTimestamp, чтобы включить также ваши критерии часов.

Возможно, загрузите таблицу #temp только первичными / уникальными ключами строк, которые соответствуют этим критериям MainView, перед соединением.

Хм ... также, если Mainview - сложное представление, перейдите прямо к базовым таблицам, чтобы загрузить эту таблицу #temp

Не забудьте использовать Profiler для проверки и определения, является ли добавление (составное, если необходимо) индексов в #temp или другую промежуточную таблицу чистым выигрышем или чистым убытком :).


1

создать составной некластеризованный индекс на mainview (typeid, timestamp).

измените свое «где» на mainview, чтобы не использовать функцию для столбцов mainview. для этого может потребоваться предварительно рассчитать эти значения как переменные перед выполнением запроса, если вам нужно, чтобы они были более динамичными.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

создать некластеризованный индекс для ACALLS.StartTime.

измените соединение на ACALLS, чтобы быть

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.