首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SqlBulkCopy是如何工作的

SqlBulkCopy是如何工作的
EN

Stack Overflow用户
提问于 2012-08-30 07:13:45
回答 3查看 7.8K关注 0票数 15

我熟悉C# SqlBulkCopy类,您可以在其中调用通过DataTable传递的'WriteToServer‘方法。

我的问题是,SQL server中的哪种底层机制用于批量插入数据?

我这样问的原因是,SQL Bulk Insert帮助文件中引用的大容量插入需要一个数据文件才能导入。SqlBulkCopy会创建数据文件吗?

我想了解一下这方面的内容,以确定是否可以在SQL中使用批量插入功能。

如果我编写一条SQL语句,准备将所有行插入到一个特定表(数千行)中,我可以将它们批量插入到目标表中吗?我现在就是这么做的,

代码语言:javascript
复制
INSERT INTO sync_filters (table_name, device_id, road_id, contract_id)
    SELECT * FROM dbo.sync_contract_filters (@device_id)

dbo.sync_contract_filters是一个生成所有要插入的行的函数。这能被批量插入吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-30 11:07:20

SqlBulkCopy不会创建数据文件。它使用可用的通信协议(命名管道、TCP/IP等)将数据表直接从.Net DataTable对象传输到服务器。并使用与BCP相同的技术将数据批量插入到目标表中。

票数 14
EN

Stack Overflow用户

发布于 2020-01-01 13:23:10

花了7年时间,但我们终于有了答案……

根据Sam Anwar的回答,我可以确认它正在将数据转换为原始字节流,并将其写入SQL,就像它是从文件中流式输入一样。我无法理解它是如何欺骗SQL使其认为它正在读取一个文件。

我想从查询内部进行大容量插入,以加快缓慢的聚集索引插入速度。在这里找到你的帖子后,不知何故我变得非常好奇,所以我花了几个小时研究它。

实际将数据写入服务器的执行路径似乎是:

你的代码:

  1. 你的代码调用System.Data.SqlClient.SqlBulkCopy.WriteToServer()

System.Data.SqlClient.SqlBulkCopy内部:

调用WriteRowSourceToServerAsync()

  • which的
  1. 调用WriteRowSourceToServerCommon()来映射列,调用WriteToServerInternalRestContinuedAsync()
  2. which的WriteToServerInternalAsync()编写data
  3. 调用AnalyzeTargetAndCreateUpdateBulkCommand() (这就是答案。跳到步骤14阅读相关内容。)CopyBatchesAsync()
  4. which (CopyBatchesAsync)调用SubmitBulkUpdateCommand()

-- System.Data.SqlClient.TdsParser内部:

调用System.Data.SqlClient.TdsParser.TdsExecuteSQLBatch()

  • which的
  1. 调用WriteString()或类似的方法将数据转换为字节数组调用WriteByteArray()
  2. which调用WritePacket()
  3. which调用WriteSni()
  4. which调用SNIWritePacket()

-- System.Data.SqlClient.SNINativeMethodWrapper内部:

调用System.Data.SqlClient.SNINativeMethodWrapper.SNIWritePacket()

  • which外部的
  1. 调用SNIWriteAsyncWrapper()或SNIWriteSyncOverAsync()

现在,这里是它变得棘手的地方。我认为这是遵循的,但我是如何做到这一点的有点老生常谈。我打开我的sni.dll副本上的文件属性,转到details选项卡,在Product Version属性中,我发现了对d0d5c7b49271cadb6d97de26d8e623e98abdc8db的“提交散列”的引用。

所以我使用googled that hash,通过this Nuget search我找到了this Nuget package,它的标题包括"System.Data.SqlClient.sni",它暗示了命名空间System.Data.SqlClient.SNI,我发现了here,但它没有正确的方法,实际上似乎不能与服务器通信。

这就是我用完了技术诀窍的地方;这是我在进入本机代码之前所能得到的最深层次的知识,我在任何地方都找不到它。尽管我不确定上面的其他噪音是什么.

SQL记住步骤4 (WriteToServerInternalRestContinuedAsync())也会调用AnalyzeTargetAndCreateUpdateBulkCommand()

  • which,在名为updateBulkCommandText的StringBuilder中连接一个查询。最后一个链接中第544行。

归根结底,它看起来只是执行一个查询(不需要文件),而实际上并没有使用 (需要文件)。注意:这两个命令看起来非常相似。

Microsoft文档中有一个重要的注意事项:

外部工具用于上载二进制数据流的

。此选项不适用于SQL Server Management Studio、SQLCMD、OSQL等工具或SQL Server Native Client等数据访问应用程序编程接口。

我将其解释为“使用风险自负,不要期待帮助”。公平地说,这几乎和绿灯一样好。

票数 8
EN

Stack Overflow用户

发布于 2012-08-30 11:34:29

SqlBulkCopy可以使用datatable、IDataReader或DataRow[]作为数据源。看一下这个类的WriteToServer方法。我发现它是一种将数据导入SQL Server的非常有用的机制。我之前已经将其与CSVReader结合使用过。前面的链接让您了解了它如何与实现IDataReader的类一起工作。

您可能需要使用play around with the batch sizes来确保获得预期的性能。

如果你想从快速写入大量数据中获得最佳性能,那么MSDN上的The Data Loading Performance Guide是一个非常有用的资源。它更侧重于像BCP和批量插入这样的东西,但涉及到SQLBulkCopy,也提供了相当多的思考食物(可能有点太多了,但它至少是一个有用的参考)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12187768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档