【问题标题】:Large SQL inserts TVF vs BULK insert大型 SQL 插入 TVF 与 BULK 插入
【发布时间】:2011-06-30 08:23:48
【问题描述】:

从 C# 应用程序中插入一个巨大的数组(10M 元素)的最快方法是什么?

到目前为止,我使用批量插入。 C# app 生成一个大的文本文件,我用 BULK INSERT command 加载它。出于好奇,我写了一个简单的用户定义的 CLR 表值函数。

[SqlFunction(Name = "getArray", FillRowMethodName = "FillRow")]
        public static IEnumerable getArray(String name)
        {
        return my_arrays[name]; // returns the array I want to insert into db
        }

        public static void FillRow(Object o, out SqlDouble sdo)
        {
            sdo = new SqlDouble((double)o);
        }

这个查询:

INSERT INTO my_table SELECT data FROM dbo.getArray('x');

工作速度几乎是等效批量的 2 倍。确切的结果是:

BULK - 330 秒(写入磁盘 + 插入) TVF - 185s

当然,这是由于写入开销,但我不知道 BULK 插入是否有任何等效的内存。

所以我的问题是 - TVF 是否比 BULK 更好(它是为大型插入创建的),还是我在这里遗漏了什么。有没有第三种选择?

【问题讨论】:

    标签: sql sql-server insert clr bulkinsert


    【解决方案1】:

    当我真的需要最后一点性能时,我会使用SqlBulkCopy,这样您就可以跳过首先将其全部放在磁盘上的开销。

    SqlBulkCopy 接受一个你必须实现的 IDataReader,但只有接口的几个方法。我总是做的只是创建class MyBulkCopySource : IDataReader,单击“实现接口”并将其提供给 BulkCopy,以查看调用了哪个方法。实现它,再试一次等​​等。你只需要实现其中的三个,其余的永远不会被调用。

    AFAIK 这是将数据从 C# 程序泵入 SqlDB 的最快方法。

    GJ

    【讨论】:

      【解决方案2】:
      • 使用 SqlBulkCopy
      • 来自多个线程,每次都有 30.000 行之类的块。
      • 不是最终表,而是临时表
      • 使用不支持锁定的连接设置从中复制。

      这完全将最小的锁定放在了最终表上。

      【讨论】:

      • 你确定多线程吗?你的意思是多个 SBC 各自都有自己的连接吗?通常我希望瓶颈是网络或磁盘驱动器。我认为使用多线程会导致争用。
      • 多线程,因此多个 SBC 同时运行。我使用它来加载大量数据(600+ 百万)并使用 3 个线程将吞吐量翻倍。在核心表上减少争用。那里的锁定时间很短,并且三个线程无论如何都使用单独的临时表实例;)始终保持数据流动。
      猜你喜欢
      • 1970-01-01
      • 2014-09-16
      • 2011-10-31
      • 1970-01-01
      • 2019-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多