У нас есть большая база данных, около 1 ТБ, на которой работает SQL Server 2014 на мощном сервере. Все работало нормально в течение нескольких лет. Около 2 недель назад мы провели полное обслуживание, которое включало: установку всех обновлений программного обеспечения; перестройте все индексы и компактные файлы БД. Однако мы не ожидали, что на определенном этапе загрузка ЦП БД увеличилась более чем на 100% до 150%, когда фактическая нагрузка была одинаковой.
После многих ошибок мы сократили его до очень простого запроса, но не смогли найти решение. Запрос чрезвычайно прост:
select top 1 EventID from EventLog with (nolock) order by EventID
Это всегда занимает около 1,5 секунд! Однако подобный запрос с «desc» всегда занимает около 0 мс:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable имеет около 500 миллионов строк; EventID
является основным столбцом кластеризованного индекса (упорядоченным ASC
) с типом данных bigint (столбец Identity). Существует несколько потоков, вставляющих данные в таблицу вверху (большие EventID), и 1 поток, удаляющий данные снизу (меньшие EventID).
В SMSS мы убедились, что два запроса всегда используют один и тот же план выполнения:
Сканирование кластерного индекса;
Предполагаемые и фактические номера строк равны 1;
Предполагаемое и фактическое количество казней равно 1;
Ориентировочная стоимость ввода / вывода 8500 (кажется высокой)
При последовательном запуске стоимость запроса равна 50% для обоих.
Я обновил статистику индекса with fullscan
, проблема сохранилась; Я снова перестроил индекс, и проблема, казалось, ушла на полдня, но вернулась.
Я включил статистику ввода-вывода с:
set statistics io on
затем выполнил два запроса последовательно и нашел следующую информацию:
(Для первого запроса, медленный)
Таблица «PTable». Сканирование 1, логическое чтение 407670, физическое чтение 0, чтение с опережением 0, логическое чтение 1, физическое чтение 1, чтение с опережением 0.
(Для второго запроса самый быстрый)
Таблица «PTable». Сканирование 1, логическое чтение 4, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.
Обратите внимание на огромную разницу в логическом чтении. Индекс используется в обоих случаях.
Фрагментация индекса может объяснить немного, но я считаю, что влияние очень мало; и проблема никогда не случалась раньше. Еще одним доказательством является то, что я запускаю запрос вроде
select * from EventLog with (nolock) where EventID=xxxx
Даже если я установлю xxxx наименьшим EventID в таблице, запрос всегда будет молниеносным.
Мы проверили, и нет проблем с блокировкой / блокировкой.
Примечание: я просто попытался упростить проблему выше. «PTable» на самом деле является «EventLog»; PID
есть EventID
.
Я получаю тот же результат тестирования без NOLOCK
подсказки.
Кто-нибудь может помочь?
Более подробные планы выполнения запросов в XML выглядят следующим образом:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
Я не думаю, что имеет значение предоставить инструкцию создания таблицы. Это старая база данных, и она прекрасно работала в течение долгого времени до тех пор, пока не началось техническое обслуживание. Мы провели много исследований сами и сузили их до информации, представленной в моем вопросе.
Таблица была создана обычно со EventID
столбцом в качестве первичного ключа, который является identity
столбцом типа bigint
. В настоящее время, я думаю, проблема в фрагментации индекса. Сразу после перестройки индекса проблема, казалось, ушла на полдня; но почему он вернулся так быстро ...?