Как мне захватить данные, переданные в 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 и триггеры при вставке строк!

Другие вопросы по тегам