【问题标题】:INSERTing data from a text file into SQL server (speed? method?)将文本文件中的数据插入 SQL 服务器(速度?方法?)
【发布时间】:2012-03-23 16:00:35
【问题描述】:

这里有一个 400 MB 的 .txt 文件,由“|”分隔。使用带有 C# 的 Windows 窗体,我将 .txt 文件的每一行插入到我的 SQL Server 数据库中的表中。

我正在做的只是这个(为简洁起见,缩写为“...”):

while ((line = file.ReadLine()) != null)
{
   string[] split = line.Split(new Char[] { '|' });

   SqlCommand cmd = new SqlCommand("INSERT INTO NEW_AnnualData VALUES (@YR1984, @YR1985, ..., @YR2012)", myconn);
   cmd.Parameters.AddWithValue("@YR1984", split[0]);
   cmd.Parameters.AddWithValue("@YR1985", split[1]);
   ...
   cmd.Parameters.AddWithValue("@YR2012", split[28]);

   cmd.ExecuteNonQuery();
}

现在,这正在工作,但需要一段时间。这是我第一次用大量数据做任何事情,所以我需要确保 A) 我正在以有效的方式做这件事,并且 B) 我的期望不会太高。

在循环进行时使用SELECT COUNT(),我可以看到数字随着时间的推移而上升和上升。所以我用了一个时钟和一些基本的数学来计算出事情的运行速度。 在 60 秒内,有 73881 次插入。那是每秒 1231 次插入。问题是,这是平均速度,还是我的表现很差?如果是后者,我该怎么做才能提高性能?

我确实读过一些关于 SSIS 准确地为此目的有效的信息。但是,我需要通过单击 Windows 窗体中的按钮来执行此操作,而不是通过 SISS。

【问题讨论】:

    标签: sql sql-server performance import flat-file


    【解决方案1】:

    噢——这种方法会给你带来令人震惊的表现。尝试使用 BULK INSERT,如下:

    BULK INSERT MyTable
        FROM 'e:\orders\lineitem.tbl'
        WITH 
        (
            FIELDTERMINATOR ='|',
            ROWTERMINATOR ='\n'
        )
    

    这是性能方面的最佳解决方案。有一个缺点,即该文件必须存在于数据库服务器上。如果您无法从运行进程的位置访问服务器的文件系统,那么我过去使用过两种解决方法。一种是在工作站上安装 SQL Express 实例,将主服务器作为链接服务器添加到工作站实例,然后运行“BULK INSERT MyServer.MyDatabase.dbo.MyTable...”。另一种选择是将 CSV 文件重新格式化为 XML,这可以非常快速地处理,然后将 XML 传递给查询并使用 OPENXML 处理它。 BULK INSERT 和 OPENXML 在 MSDN 上都有很好的记录,您最好通读这些示例。

    【讨论】:

    • 这个简单的方法很好。对于导入向导每分钟加载 100,000 条记录的同一文件,我在 2 分钟内加载了 650 万条记录:快 40 倍。
    【解决方案2】:

    我必须同意安多马尔的观点。我真的很喜欢 SqlBulkCopy。它真的很快(您需要play around with BatchSizes 以确保找到适合您情况的。)

    有关讨论各种选项的真正深入的文章,请查看 Microsoft 的“数据加载性能指南”; http://msdn.microsoft.com/en-us/library/dd425070(v=sql.100).aspx

    另外,看一下带有CSV Reader 的SqlBulkCopy 的C# 示例。它不是免费的,但是如果您可以在更短的时间内编写一个快速准确的解析器,那就去吧。至少,它会给你一些想法。

    【讨论】:

      【解决方案3】:

      我认为 SSIS 比这种类型的方法要快得多,但是有很多变量会影响性能。

      如果您想试验 SSIS,请使用 Management Studio 中的导入和导出向导生成一个 SSIS 包,该包将导入一个竖线分隔的文件。您可以保存包并从 .NET 应用程序运行它

      有关如何以编程方式运行 SSIS 包的信息,请参阅这篇文章:http://blogs.msdn.com/b/michen/archive/2007/03/22/running-ssis-package-programmatically.aspx。它包括有关如何从客户端、服务器或任何地方运行的选项。

      此外,请查看这篇文章,了解总体上提高批量插入性能的其他方法。 http://msdn.microsoft.com/en-us/library/ms190421.aspx

      【讨论】:

      • 这不需要客户端部署 SSIS 组件吗?如果升级 SQL Server 版本,SSIS 包通常也需要更新。
      • 上面的链接详细介绍了从代码执行 SSIS 包的多种方法,其中 3 种可以远程运行,包括选项,无需部署客户端工具。此外,我不需要对从 05 到 08 再到 R2 的 SSIS 包进行任何更改。 YMMV。
      【解决方案4】:

      查看SqlBulkCopy on MSDNnice blog post here。对我来说,每秒插入数万次。

      【讨论】:

      • 这正是我所需要的。起初我在使用它时遇到了问题,因为数据太多以至于我遇到了 OutOfMemory 异常,但这篇文章让我走上了正确的道路:stackoverflow.com/questions/9442171/…
      猜你喜欢
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2017-02-06
      • 2018-07-28
      相关资源
      最近更新 更多