【问题标题】:Is it better to pass large inserts to SQL Server as a table valued parameter, or as a string insert statement?将大型插入作为表值参数还是作为字符串插入语句传递给 SQL Server 是否更好?
【发布时间】:2012-05-25 15:27:17
【问题描述】:

我正在编写一个将数据写入 SQL Server 2008r2 的 .NET 应用程序。我有两个插入数据的选项,我可以创建一个大字符串插入语句,并将其作为文本命令发送,或者我可以在 .NET DataTable 中收集数据,并将其作为表值参数传递。每种方法的好处和成本是什么?

(我省略了很多代码,因为我只是询问相对的好处,而不是具体的语法)

例如:

选项 1:

    string insert = @"insert into MyTable (id, val) values
        ( 1, 'a'),(2,'b'),(3,'c'),(4,'d');"

选项 2:

    DataTable dt = new DataTable();
    dt.Columns.Add("id", typeof(int));
    dt.Columns.Add("val", typeof(string));
    ....
    create procedure uspMyProc 
                    @tt ttMyTableType readonly
                as
                begin
                    insert into TestTable1 (id, strValue)
                    select myId, myVal from @tt;
                end"

感谢您的帮助。

【问题讨论】:

  • 选项#3。使用 SqlCommand。该结构可以是动态的(当且仅在需要时),同时保持数据参数化。
  • (正确使用事务时,许多 SqlCommand 插入速度非常快。)

标签: c# .net sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

选项 3: 在第一个实例中,我将使用一个插入语句的参数值填充插入存储过程,并在 C# 代码的循环中多次调用它:

选项 4:如果您确实有 很多 行要插入,也许您需要查看 SqlBulkCopy class。它消耗DataTableDataRowIDataReader。您可以使用一些自定义代码从对象列表中创建一个IDataReader,这里提出了类似的问题:

Get an IDataReader from a typed List


我会说这取决于。

如果您真的想以表格形式传递多行参数,无论出于何种原因,请使用表值参数 - 这就是它的用途。

我已经看到了选项 1 - 一些通用 DAL 代码会编写一个 SQL“批处理”命令来运行。它有效,但没有对注入攻击提供任何防御。参数化的 SQL 确实如此。


话虽如此,我更愿意为要从代码中插入的每一行调用一次插入存储过程 - 调用将完全参数化并且性能很好。如果性能成为问题,我会支持选项 4。

【讨论】:

  • 还有助于防御 SQL 注入
  • 谢谢。我不知道 SqlBulkCopy 类。我认为这正是我想要的。
【解决方案2】:

大有多大?如果它很大,没有什么比 SqlBulkCopy 更好的了。实际上,我发现 TVP 的表现令人失望。对于查询计划的重用,我是参数化和大规模重用语句的粉丝。 Dapper 可以帮助解决这个问题,允许您将对象列表传递给查询 - 然后它将按成员名称添加每个对象的命名参数,每秒执行数千次操作。例如:

conn.Execute(
    "insert foo (Id,Name) values (@Id,@Name)",
    listOfObjects);

这将迭代列表并依次使用每个对象中的.Id.Name 来执行查询。

【讨论】:

  • 请提供 Drapper 的链接
  • @Blam 要么在 nuget 中输入“dapper”,要么:code.google.com/p/dapper-dot-net(这是我们在 stackoverflow 上用于高性能数据访问的自定义堆栈)
【解决方案3】:

值限制为 1000

而且值似乎有一些性能问题

Insert Performance Issues With Multiple Values

我使用 TVP 插入数千行,它对我来说非常有用。我使用 List 集合作为 TVP 源,因为 DataTable 有更多开销。如果可以,插入按 PK 排序的行。

话虽如此,我将尝试 Marc Gravell 的答案。

JNK 普遍不信任 TVP。

【讨论】:

  • 您确定 DataTable 和开销与 Enumerable 类型以及每条记录在每条记录上从 c# 到 sqlserver 的往返行程吗? (我遇到这个问题只是因为我研究了这个问题)我的问题 [stackoverflow.com/questions/34365407/… 在其中我尝试使用它通过记录 ID 进行多次删除。
  • “数据在客户端被结构化为一组强类型行,并在一次往返中最终在服务器上作为一组强类型行” 来自 - lennilobel.wordpress.com/2009/07/29/…
  • @Robb_2015 你确定你读过我的回答吗?价值观清楚地解决了选项 1:。至于Option2,我说它(TVP)效果很好。在我的回答中,我没有断言 TVP 不是严格输入的,也不会导致多次往返。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多