Производительность вставки увеличивается под нагрузкой: почему?


19

У меня есть кусок кода, который выполняет вставки в сильно денормализованные таблицы. Таблицы имеют количество столбцов в диапазоне от ~ 100 до 300+. Это SQL Server 2008 R2, работающий на Windows Server 2008.

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

Когда я выполняю вставки, скажем, 500 раз, неоднократно вызывая фрагмент кода, который выполняет вставку, я получаю в среднем ~ 360 мс.

Странно то, что когда я запускаю тестовый код одновременно, используя 4 процесса (один и тот же exe-файл запускается из 4 разных командных строк в Windows Server 2008), производительность вставки для вызова становится намного выше. Я вижу всплески, которые идут со скоростью 90 мс (почти X4 быстрее). Я измеряю время вставки из кода.

Поскольку 4 процесса ничего не знают друг о друге, я предполагаю, что это как-то связано с SQL Server, но я понятия не имею, почему. Я хотел бы знать, почему это происходит, и если есть какая-либо конфигурация, которая позволила бы мне получить такую ​​же производительность, когда вставки не так часто.

Предложения, касающиеся методов мониторинга SQL Server, чтобы понять, что происходит на уровне БД, также приветствуются.

Ответы:


15

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

Чтобы определить, является ли пропускная способность / размер сброса журнала транзакций фактором, следите за:

Ищите внутренние пределы достижимы. В SQL Server 2008 R2 может быть не более 32 ожидающих (асинхронных) операций сброса журнала в каждой базе данных в 64-разрядных версиях (только 8 в 32-разрядных). Существует также ограничение на общий размер выдающихся операций ввода-вывода в 3840 КБ.

Больше информации и дальнейшее чтение:


12

Все, что говорит @PaulWhite, плюс ...

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

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

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

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


Спасибо, Роб. Моя проблема с производительностью связана с большим количеством таблиц, используемых во время вставки. Внешних ключей нет, я удалил их по соображениям производительности, и мои требования к модели и домену позволяют мне это делать. Я не загружаю данные в оперативную память, и мои вставки динамически формируются входящими запросами, которые постоянно меняются. Я в основном неправильно использую схему «звезда / снежинка» для OLTP и пытаюсь добиться максимальной производительности.
Махоня

2
@mahonya, даже если вы явно не загружаете данные в ОЗУ, SQL Server должен сначала прочитать необходимый индекс и страницы данных в буферный кеш перед выполнением операции вставки. Параллельные потоки вставки могут иметь эффект разогрева кеша, так что один поток переносит накладные расходы на чтение, а другой обращается к данным в кеше.
Дан Гузман

Спасибо @DanGuzman - и да, Махоня, есть большая вероятность того, что ваш кеш приятно нагревается. Я бы проверил ваши ожидания, чтобы увидеть, не является ли физический ввод-вывод причиной вашего узкого места.
Роб Фарли

Спасибо @DanGuzman Согласен, ускорение кэша индекса db - это то, что я привык видеть в postgres. Я, вероятно, неправильно понял ввод Роба.
Махоня

-3

некоторые серверы / процессоры / операционные системы запоминают шаблоны. как кеш.

Поскольку вы делаете одно и то же 4 раза, я уверен, что есть способы, которые могут срезать углы. Я предполагаю, что в первом случае вы думаете об этом как об одном долгом процессе (пример 1), но вторым способом is видит повторно использованный код и запускает его как кеш (example2), или это может быть первый процесс, который должен вместить его в (ram example3).

пример1: 0111110000110111110000111011111000011110111110000

пример2: 0111110000 | 11 | 0111110000 | 111 | 0111110000 | 1111 | 0111110000

пример3: 0111110000011111000001111100000111110000 пример3: цикл: 0111110000

Я знаю, что сервер Ubuntu делает это с повторными запросами MySQL. Я могу сохранить их в кеше, хотя на самом деле единственная разница во времени составляет 10-40 мм, но это складывается. Когда я учился в школе, были классы, которые показали, что вы должны заставить программы (perl / php) использовать этот кеш, чтобы быть быстрее.

Но это может зависеть от программы, на каком языке, на каком языке она была скомпилирована или как она была запрограммирована.

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