如何使用Sql Profiler捕获在SqlBulkCopy中传递的数据?

时间:2016-02-03 19:46:12

标签: sql-server sql-server-2012 bulkinsert sqlbulkcopy sql-server-profiler

我一直在使用Sql Profiler来捕获SQL语句并重新运行有问题的语句。非常有用。

但是,有些代码使用SqlBulkCopy API,我不知道如何捕获它们。我看到临时表的创建,但没有任何填充它们。似乎SqlBulkCopy绕过了Sql Profiler,或者我没有捕获正确的事件。

2 个答案:

答案 0 :(得分:8)

捕获批量插入操作的事件信息(BCP.EXESqlBulkCopy,我认为BULK INSERTOPENROWSET(BULK...)是可能的,但您不会成为能够看到各个行和列。

批量插入操作显示为单个(好,每个批次一个,默认是在一个批次中执行所有行)DML语句:

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

您可以找到&#34;提示&#34;的完整列表。在BCP Utility的MSDN页面上。请注意,SqlBulkCopy仅支持这些提示的子集(例如KEEP_NULLSTABLOCK和其他一些提示),但支持ORDER(...)或{{1 } ** (实际上,这是非常不幸的,因为需要ROWS_PER_BATCH=提示以避免在tempdb中发生的排序以便允许最小程度地记录操作(假设此类操作的其他条件也已得到满足。)

要查看此语句,您需要捕获SQL Server Profiler中的以下任何事件:

  

SQL:BatchStarting
  SQL:BatchCompleted
  SQL:StmtStarting
  SQL:StmtCompleted事件

您还希望至少选择以下列(在SQL Server Profiler中):

  

的TextData
  CPU
  读取
  写
  持续时间
  SPID
  开始时间
  结束时间
  RowCounts

而且,由于用户无法直接提交ORDER()语句,如果您只想查看这些事件而不是其他任何内容,则可以在列过滤器中对其进行过滤。

如果您想查看INSERT BULK操作开始和/或结束的正式通知,则需要捕获以下事件:

  

的SqlTransaction

然后添加以下Profiler列:

  

EventSubClass
  的ObjectName

对于BULK INSERT,您将始终获得显示&#34; BULK INSERT&#34;以及是开始还是结束是由ObjectName中的值决定的,它是&#34; 0 - 开始&#34;或&#34; 1 - 提交&#34; (我想如果它失败了你应该看到&#34; 2 - 回滚&#34;)。

如果未指定EventSubClass提示(并且再次使用ORDER()无法指定),那么您还将获得&#34; SQLTransaction&# 34;事件显示&#34; sort_init&#34;在SqlBulkCopy列中。这个事件也有&#34; 0 - 开始&#34;和&#34; 1 - 提交&#34;事件(如ObjectName列中所示)。

最后,即使您看不到特定的行,如果捕获以下事件,仍然可以看到针对事务日志的操作(例如插入行,修改IAM行,修改PFS行等):

  

TransactionLog

并添加以下Profiler列:

  

的ObjectID

感兴趣的主要信息将在EventSubClass列中,但遗憾的是它只是ID值,我在MSDN文档中找不到这些值的任何翻译。但是,我确实找到了Jonathan Kehayias的以下博文:Using Extended Events in SQL Server Denali CTP1 to Map out the TransactionLog SQL Trace Event EventSubClass Values

@RBarryYoung指出可以在EventSubClass目录视图中找到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 :( 属性相当于为 BCP.EXE 设置SqlBulkCopy.BatchSize选项,这是一项操作设置它控制每个命令如何将行分解为集合。这与-b提示不同,后者没有物理控制行如何分解成集,而是允许SQL Server更好地规划它将如何分配页面,从而减少了条目的数量。事务日志(有时相当多)。我的测试仍显示:

  • BCP.EXE 指定ROWS_PER_BATCH=确实将-b提示设置为相同的值。
  • 指定ROWS_PER_BATCH=属性设置SqlBulkCopy.BatchSize提示,但是,减少事务日志活动的好处肯定存在(魔术?)。事实上净效应仍然可以获益,这就是为什么当我说ROWS_PER_BATCH=不支持ORDER()提示是不幸的时候我没有提到它的原因。

答案 1 :(得分:0)

您无法在SQL事件探查器中捕获SqlBulkCopy,因为在SQL Server表中插入数据时,SqlBulkCopy根本不会生成SQL。 SqlBulkCopy的工作方式类似于bcp实用程序,并将数据直接加载到SQL Server文件系统中。插入行时甚至是can ignore FKs and triggers