SQL Server 2005: Повышение производительности для тысяч или запросов на вставку. время выхода-входа = 120 мс

Может ли кто-нибудь пролить свет на то, как SQL Server 2005 обрабатывает запросы, выдаваемые клиентом с использованием ADO.NET 2.0. Ниже приведен сокращенный вывод SQL Trace. Я вижу, что пул соединений работает (я полагаю, что в пул входит только одно соединение). Что мне не ясно, так это то, почему у нас так много вызовов sp_reset_connection, т.е. последовательность: Аудит входа в систему, SQL: BatchStarting, RPC: Starting и Аудит выхода из системы для каждого цикла в цикле for ниже. Я вижу постоянное переключение между базой данных tempdb и master, что приводит меня к выводу, что мы потеряли контекст при создании следующего соединения путем его извлечения из пула на основе аргумента ConectionString.

Я вижу, что каждые 15 мс я могу получить 100-200 входов/выходов в секунду (в то же время сообщает Profiler). Через 15 мс у меня снова серия из 100-200 входов/выходов в секунду.

Мне нужно разъяснение того, как это может повлиять на многие сложные запросы на вставку в производственной среде. Я использую Enterprise Library 2006, код скомпилирован с VS 2005, и это консольное приложение, которое анализирует плоский файл с 10 тысячами строк, группирующих родительско-дочерние строки, запускается на сервере приложений и запускает 2 хранимые процедуры на удаленном SQL Сервер 2005 вставляя родительскую запись, извлекает значение Identity и с его помощью вызывает вторую хранимую процедуру 1, 2 или несколько раз (иногда несколько тысяч) вставляя дочерние записи. Дочерняя таблица содержит около 10 миллионов записей с 5-10 индексами, некоторые из которых не кластеризованы. Существует довольно сложный триггер Insert, который копирует вставленную детальную запись в архивную таблицу. Всего у меня всего 7 вставок в секунду, а это значит, что на 50 тысяч записей может уйти 2-4 часа. Когда я запускаю Profiler на тестовом сервере (это почти эквивалентно рабочему серверу), я вижу, что между записями трассировки Audit Logout и Audit Login проходит около 120 мс, что почти дает мне возможность вставить около 8 записей.

Итак, мой вопрос заключается в том, есть ли способ улучшить вставку записей, поскольку компания загружает 100 тысяч записей и занимается ежедневным планированием, а также имеет SLA для выполнения запросов клиентов, поступающих в виде заказов на плоские файлы, и необходимо обработать некоторые большие файлы> 10 тысяч ( привозят быстро). 4 часа на ввоз 60 тысяч надо сократить до 30 минут.

Я думал использовать BatchSize DataAdapter для отправки нескольких вызовов хранимых процедур, массовых вставок SQL для групповой вставки из DataReader или DataTable, быстрой загрузки SSIS. Но я не знаю, как правильно анализировать повторную индексацию и статистику населения, и, возможно, это займет некоторое время. Что еще хуже, компания использует самую большую таблицу для отчетности и другой онлайн-обработки, а индексы не могут быть удалены. Я управляю транзакцией вручную, устанавливая значение поля и выполняя транзакционное обновление, изменяя это значение на новое значение, которое другие приложения используют для получения зафиксированных строк.

Посоветуйте, как подступиться к этой проблеме. На данный момент я пытаюсь создать промежуточные таблицы с минимальным ведением журнала в отдельной базе данных и без индексов, и я попытаюсь выполнить пакетную (массовую) вставку родительских дочерних элементов. Я считаю, что производственная БД имеет простую модель восстановления, но это может быть полное восстановление. Если пользователь БД, который используется моим консольным приложением .NET, имеет роль bulkadmin, означает ли это, что его массовые вставки минимально регистрируются. Я понимаю, что когда таблица кластеризована, и многие некластеризованные индексы, которые вставляются, все еще регистрируются для каждой строки.

Пул подключений работает, но с большим количеством входов/выходов. Почему?

for (int i = 1; i ‹= 10000; i++){ использование (SqlConnection conn = new SqlConnection («сервер = (локальный); база данных = master; интегрированная безопасность = sspi;»)) {conn.Open(); используя (SqlCommand cmd = conn.CreateCommand()){ cmd.CommandText = "использовать tempdb"; cmd.ExecuteNonQuery();}}}

Трассировка профилировщика SQL Server:

Аудит главного входа в систему 13.01.2010 23:18:45.337 1 - Без пула
SQL:BatchStarting использовать tempdb master 2010-01-13 23:18:45.337
RPC:Starting exec sp_reset_conn tempdb 2010-01-13 23 :18:45.337
Аудит выхода из tempdb 2010-01-13 23:18:45.337 2 - Объединенный
Аудит входа -- мастер сетевого протокола 2010-01-13 23:18:45.383 2 - Объединенный
SQL :BatchStarting use tempdb master 13.01.2010 23:18:45.383
RPC:Starting exec sp_reset_conn tempdb 13.01.2010 23:18:45.383

Аудит Выход из tempdb 13.01.2010 23: 18:45.383 2 - Объединенный
Аудит входа в систему -- мастер сетевого протокола 2010-01-13 23:18:45.383 2 - Объединенный
SQL:BatchStarting use tempdb master 2010-01-13 23:18:45.383
RPC:Запуск exec sp_reset_conn tempdb 2010-01-13 23:18:45.383
Аудит Выход из системы tempdb 13-01-2010 23:18:45.383 2 - Объединенный


person Rad    schedule 14.01.2010    source источник


Ответы (2)


Что вы подразумеваете под "запись в файлы журнала". Вы имеете в виду, что мне нужно разобрать плоский файл, выполнить преобразования локальных полей, выполнить некоторые вычисления на основе родительских и подробных строк и вывести в файл с разделителями в файловой системе или в формате, ожидаемом файлом BCP fmt, и использовать массовую вставку. Я думаю использовать любой из этих методов: Ускорение операций копирования с помощью SqlBulkCopy на eggheadcafe.com

Шаблон производитель/потребитель http://sqlblog.com/blogs/alberto_ferrari/archive/2009/11/30/sqlbulkcopy-performance-analysis.aspx

Спасибо, Рэд

person Rad    schedule 14.01.2010

Если у вас есть среда с высокой вставкой, и пользователю, запрашивающему вставку, не нужны какие-либо немедленные данные, полученные в результате фактической вставки, я настоятельно рекомендую группировать вставки. Вместо того, чтобы позволять 200 различным пользователям одновременно пытаться вставлять данные в одну и ту же таблицу, вы можете либо (а) записать в файлы журналов, а затем использовать BULK INSERT / BCP / SSIS для импорта данных с желаемой частотой (баланс как быстро данные на самом деле должны отражаться в базе данных и насколько разбросанной должна быть деятельность), или (б) запись в несколько различных промежуточных таблиц, а затем их округление снова с желаемой частотой. И (а), и (б) значительно ослабят разногласия; (a) немного лучше, потому что вы можете перевести базу данных полностью в автономный режим, и приложение все равно будет работать нормально.

person Aaron Bertrand    schedule 14.01.2010