Я использую 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
sp_whoisactive
: ссылкиОтветы:
У вас есть запрос без SARGable - даже если у вас хорошие индексы, вы не используете их в этом запросе.
Во-первых, реакция коленного рывка на pageiolatch_sh - это чтение страниц с диска в буфер; у вас недостаточно оперативной памяти для данных, которые он пытается извлечь.
Во-вторых, вам нужно посмотреть на план выполнения и его использование индексов - или их отсутствие.
Прекратите использовать функции в своих объединениях и в своем WHERE и получите только те данные, которые вам абсолютно необходимы для начала.
«МЕЖДУ ACALLS.StartTime и DATEADD (ss, -5, ACALLS.StartTime)» - избавиться от этого DATEADD в BETWEEN.
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 или другую промежуточную таблицу чистым выигрышем или чистым убытком :).
источник
создать составной некластеризованный индекс на mainview (typeid, timestamp).
измените свое «где» на mainview, чтобы не использовать функцию для столбцов mainview. для этого может потребоваться предварительно рассчитать эти значения как переменные перед выполнением запроса, если вам нужно, чтобы они были более динамичными.
создать некластеризованный индекс для ACALLS.StartTime.
измените соединение на ACALLS, чтобы быть
насколько я понимаю, это будет обрабатывать вашу логику и соединения с довольно высокой производительностью и избавит вас от ввода-вывода.
Мое лучшее предположение относительно того, с чем вы сталкиваетесь, заключается в том, что ваши данные сбрасываются из кэша и / или время от времени выливается на диск tempdb, поэтому лучшее решение, которое я обычно нахожу, состоит в том, чтобы лучше писать запросы просто ограничьте использование базы данных tempdb и памяти, и основные проблемы исчезнут.
источник