У нас есть база данных для продукта, который тяжело писать. Мы только что купили новую серверную машину с SSD, чтобы помочь. К нашему удивлению, вставки были не быстрее, чем на нашей старой машине с гораздо более медленным хранилищем. Во время бенчмаркинга мы заметили, что частота операций ввода-вывода, демонстрируемая процессом SQL Server, была очень низкой.
Например, я запустил скрипт, найденный на этой странице , за исключением того, что я добавил BEGIN TRAN и COMMIT вокруг цикла. В лучшем случае я видел, как использование диска достигало 7 Мбит / с, а процессор едва касался 5%. На сервере установлено 64 ГБ, и он использует 10. Общее время выполнения составило 2 минуты 15 секунд для первого вызова и примерно до 1 минуты для последующих вызовов. База данных находится на простом восстановлении и не работала во время теста. Я бросил стол между каждым звонком.
Почему такой простой скрипт такой медленный? Аппаратное обеспечение практически не используется. Как специализированные инструменты для тестирования дисков, так и SQLIO указывают на то, что твердотельный накопитель работает правильно со скоростью более 500 Мбит / с для чтения и записи. Я понимаю, что случайные записи выполняются медленнее, чем последовательные записи, но я ожидаю, что простая вставка, подобная этой, в таблицу без кластерной индексации будет намного быстрее.
В конечном итоге наш сценарий намного сложнее, но я чувствую, что сначала мне нужно разобраться в простом случае. В двух словах, наше приложение удаляет старые данные, затем использует SqlBulkCopy для копирования новых данных в промежуточные таблицы, выполняет некоторую фильтрацию и, наконец, использует MERGE и / или INSERT INTO в зависимости от случаев для копирования данных в финальные таблицы.
-> РЕДАКТИРОВАТЬ 1: Я следовал процедуре, связанной Мартином Смитом, и получил следующий результат:
[Wait Type] [Wait Count] [Total Wait (ms)] [T. Resource Wait (ms)] [T. Signal Wait (ms)]
NETWORK_IO 5008 46735 46587 148
LOGBUFFER 901 5994 5977 17
PAGELATCH_UP 40 866 865 1
SOS_SCHEDULER_YIELD 53279 219 121 98
WRITELOG 5 145 145 0
PAGEIOLATCH_UP 4 58 58 0
LATCH_SH 5 0 0 0
Я нахожу странным, что NETWORK_IO занимает большую часть времени, учитывая, что нет никакого результата, который нужно отображать, и нет данных, которые нужно передавать куда-либо, кроме файлов SQL. Включает ли тип NETWORK_IO все операции ввода-вывода?
-> РЕДАКТИРОВАТЬ 2: Я создал 20 ГБ RAM-диск и оттуда смонтировал базу данных. Лучшее время, которое у меня было на SSD - 48 с, а с RAM-диска оно уменьшилось до 37 секунд. NETWORK_IO по-прежнему самое большое ожидание. Максимальная скорость записи на RAM-диск составляла около 250 Мбит / с, тогда как он способен обрабатывать несколько гигабайт в секунду. Он по-прежнему не использует много процессора, так что же удерживает SQL?
NETWORK_IO
могут быть сообщения из 3 миллионов сообщений, "затронутых 1 строкой". Вы пробовали добавить SET NOCOUNT ON
в скрипт?
EE_WaitStats*.xel
так что старые будут загрязнять ваши результаты.
SET NOCOUNT ON
к этому тоже.