Как мне захватить данные, переданные в SqlBulkCopy, используя Sql Profiler?
Я использую Sql Profiler все время для захвата операторов SQL и повторного запуска проблемных. Очень полезно.
Однако, некоторый код использует API SqlBulkCopy, и я понятия не имею, как их захватить. Я вижу создание временных таблиц, но ничего, что заполняет их. Похоже, SqlBulkCopy обходит Sql Profiler или я не фиксирую правильные события.
2 ответа
Получение информации о событии для массовых операций вставки (BCP.EXE
, SqlBulkCopy
и я предполагаю BULK INSERT
, а также OPENROWSET(BULK...
) возможно, но вы не сможете увидеть отдельные строки и столбцы.
Операции массовой вставки отображаются в виде одного (ну, по одной на пакет, а по умолчанию все строки в одном пакете по умолчанию):
INSERT BULK <destination_table_name> (
<column1_name> <column1_datatype> [ COLLATE <column1_collation> ], ...
) [ WITH (<1 or more hints>) ]
<hints> := KEEP_NULLS, TABLOCK, ORDER(...), ROWS_PER_BATCH=, etc
Вы можете найти полный список "подсказок" на странице MSDN для утилиты BCP. Обратите внимание, что SqlBulkCopy поддерживает только подмножество этих подсказок (например, KEEP_NULLS
, TABLOCK
и несколько других) но не поддерживает ORDER(...)
или же ROWS_PER_BATCH=
** (что весьма прискорбно, так как ORDER()
подсказка необходима для того, чтобы избежать сортировки, которая происходит в базе данных tempdb, чтобы позволить минимально регистрировать операцию (при условии, что другие условия для такой операции также были выполнены).
Чтобы увидеть этот оператор, вам нужно захватить любое из следующих событий в SQL Server Profiler:
SQL: BatchStarting
SQL: BatchCompleted
SQL:StmtStarting
SQL:StmtCompleted
Вы также захотите выбрать, по крайней мере, следующие столбцы (в SQL Server Profiler):
TextData
ЦПУ
Читает
Записывает
продолжительность
ИСП
Начальное время
Время окончания
RowCounts
И, поскольку пользователь не может представить INSERT BULK
Заявление напрямую, вы, вероятно, можете фильтровать это в Фильтрах столбцов, если вы просто хотите увидеть эти события и ничего больше.
Если вы хотите увидеть официальное уведомление о том, что BULK INSERT
операция начинается и / или заканчивается, тогда вам нужно захватить следующее событие:
SqlTransaction
и затем добавьте следующие столбцы Profiler:
EventSubClass
ObjectName
За ObjectName
вы всегда будете получать события, показывающие "BULK INSERT", и то, начинается это или заканчивается, определяется значением в EventSubClass
Это либо "0 - Begin", либо "1 - Commit" (и, я полагаю, в случае неудачи вы должны увидеть "2 - Rollback").
Если ORDER()
подсказка не указана (и опять же, ее нельзя указывать при использовании SqlBulkCopy
), то вы также получите событие "SQLTransaction", показывающее "sort_init" в ObjectName
колонка. Это событие также имеет события "0 - Начало" и "1 - Фиксация" (как показано на EventSubClass
колонка).
Наконец, даже если вы не видите определенные строки, вы все равно можете видеть операции с журналом транзакций (например, вставить строку, изменить строку IAM, изменить строку PFS и т. Д.), Если вы захватили следующее событие:
Журнал транзакций
и добавьте следующий столбец Profiler:
ObjectID
Основная информация, представляющая интерес будет в EventSubClass
столбец, но, к сожалению, это просто значения ID, и я не смог найти перевод этих значений в документации MSDN. Однако я нашел следующее сообщение в блоге Джонатана Кейяса: Использование расширенных событий в SQL Server Denali CTP1 для сопоставления значений EventSubClass события трассировки SQL Transaction Log.
@RBarryYoung указал, что значения и имена EventSubClass можно найти в sys.trace_subclass_values
представление каталога, но запрос этого представления показывает, что в нем нет строк для TransactionLog
событие:
SELECT * FROM sys.trace_categories -- 12 = Transactions
SELECT * FROM sys.trace_events WHERE category_id = 12 -- 54 = TransactionLog
SELECT * FROM sys.trace_subclass_values WHERE trace_event_id = 54 -- nothing :(
** Обратите внимание, что SqlBulkCopy.BatchSize
свойство эквивалентно установке -b
опция для BCP.EXE, которая является рабочим параметром, который управляет тем, как каждая команда разбивает строки на наборы. Это не то же самое, что ROWS_PER_BATCH=
подсказка, которая физически не контролирует, как строки разбиваются на наборы, но вместо этого позволяет SQL Server лучше планировать, как он будет распределять страницы, и, следовательно, уменьшает количество записей в журнале транзакций (иногда совсем немного). Еще мое тестирование показало, что:
- указав
-b
для BCP.EXE установилROWS_PER_BATCH=
намек на это же значение. - указав
SqlBulkCopy.BatchSize
собственность не установилаROWS_PER_BATCH=
подсказка, НО, выгода от снижения активности Transaction Log была как-то определенно (магия?). Тот факт, что чистый эффект заключается в том, чтобы по-прежнему получать выгоду, объясняет, почему я не упомянул об этом в верхней части, когда сказал, что, к сожалению,ORDER()
подсказка не была поддержанаSqlBulkCopy
,
Вы не можете захватить SqlBulkCopy
в SQL Profiler, потому что SqlBulkCopy
вообще не генерирует SQL при вставке данных в таблицу SQL Server. SqlBulkCopy
работает аналогично bcp
утилита и загружает данные непосредственно в файловую систему SQL Server. Он даже может игнорировать FK и триггеры при вставке строк!