将大规模CSV文件上载到SQL Server数据库

时间:2009-05-12 16:06:32

标签: c# .net sql-server .net-2.0 csv

我需要将大量(16GB,6500万条记录)CSV文件上传到SQL Server 2005数据库中的单个表。有没有人对最佳方法有任何指示?

详情

我目前正在使用C#控制台应用程序(.NET framework 2.0)将导入文件拆分为50000条记录的文件,然后处理每个文件。我使用SqlBulkCopy类将数据从控制台应用程序上传到数据库中,批量为5000.分割文件大约需要30分钟,上传整个数据集(6500万条记录)大约需要4.5小时。生成的文件大小和批量上载大小都是配置​​设置,我正在研究增加两者的值以提高性能。要运行该应用程序,我们使用具有16GB RAM的四核服务器。该服务器也是数据库服务器。

更新

鉴于目前为止的答案,请注意在导入之前:

  • 数据库表被截断,所有索引和约束都被删除。
  • 数据库收缩,磁盘空间被回收。

导入完成后:

  • 重建索引

如果您可以建议任何不同的方法,或者我们可以改进现有导入应用程序的方法,我将不胜感激。感谢。

相关问题

以下问题可能对处理此问题的其他人有用:

解决方案

我已经研究了改变批量大小和拆分文件大小的影响,发现批量500条记录和200,000条记录的拆分文件最适合我的应用程序。使用SqlBulkCopyOptions.TableLock也有帮助。有关详细信息,请参阅此question的答案。

我还研究了使用SSIS DTS包和BULK INSERT SQL脚本。 SSIS包看起来更快,但没有让我能够记录无效记录等。BULK INSERT SQL脚本虽然比SSIS包慢,但比C#应用程序要快得多。它确实允许我记录错误等,因此,我接受来自ConcernedOfTunbridgeWellsBULK INSERT答案作为解决方案。我知道这对于遇到这个问题的每个人来说可能不是最好的答案,但它解决了我当前的问题。

感谢所有回复的人。

此致,MagicAndi

11 个答案:

答案 0 :(得分:5)

BULK INSERT从DBMS本身运行,从服务器上的目录中读取bcp控制文件描述的文件(或安装在其上)。编写一个将文件拆分为较小块的应用程序,将它们放在适当的目录中,执行一个执行一系列BULK INSERTS的包装器。如有必要,您可以并行运行多个线程。

这可能与批量负载一样快。此外,如果批量加载文件中有合适的分区键,请将分段表放在分区方案上。

此外,如果要批量加载到具有聚簇索引的表中,请确保数据的排序顺序与索引相同。合并排序是大数据集的朋友。

答案 1 :(得分:3)

您是否尝试过SSIS(SQL Server Integration Services)。

答案 2 :(得分:2)

您已经使用的SqlBulkCopy课程将是您最好的选择。从c#代码中可以做到的最好的方法就是试验您的特定系统和数据,以了解哪种批量大小最佳。但你已经这样做了。

除了客户端代码之外,您可以使用服务器执行某些操作以使导入更有效:

  • 尝试在开始导入之前设置表和数据库大小,使其足够大以容纳整个集合。你不想在这个过程中依赖自动增长。

  • 根据数据的排序方式和表中的任何索引,您可以更好地删除与导入记录的顺序不匹配的任何索引,然后在以后重新创建它们导入。

  • 最后,尝试并行运行它很诱人,一些线程一次进行批量插入。但是,最大的瓶颈几乎可以肯定是磁盘性能。您可以对物理服务器进行任何改进(新磁盘,san等)的任何操作都会有所帮助。

答案 3 :(得分:2)

您可以按如下方式保存拆分文件的步骤:

  • 实例化IDataReader以读取输入CSV文件中的值。有几种方法可以做到这一点:最简单的方法是使用Microsoft OleDb Jet驱动程序。如果您需要更多信息,可以使用谷歌 - 例如this StackOverflow question中有一些信息。

    另一种方法是使用www.csvreader.com使用的技术。

  • 实例化SqlBulkCopy对象,将BatchSize和BulkCopyTimeout属性设置为适当的值。

  • 将IDataReader传递给SqlBulkCopy.WriteToServer方法。

我已成功使用此技术处理大型文件,但不如您的大。

答案 4 :(得分:1)

请参阅thisthis博客文章以进行比较。 似乎最好的选择是使用BulkInsert并将TABLOCK选项设置为true。

答案 5 :(得分:0)

您是否尝试在Sql Server中使用Bulk Insert method

答案 6 :(得分:0)

最近,我不得不上传/导入很多东西(构建一个PHP脚本)。

我决定将它们记录下来进行记录。

当然,这需要更长的时间,但对我来说,以下几点非常重要: - 轻松暂停该过程 - 更好的调试

这只是一个提示。

的问候, 本尼迪克特

答案 7 :(得分:0)

BULK INSERT可能已经是最快的方式了。通过在稍后插入和重新建立索引和约束时删除索引和约束,可以获得额外的性能。最高性能影响来自聚簇索引。

答案 8 :(得分:0)

您是否尝试过SQL Server Integration Services?它可能能够更好地处理如此大的文本文件

答案 9 :(得分:0)

只是要检查一下,如果你插入的桌子上没有索引,你的插入会更快。

答案 10 :(得分:0)

我这样做的场景是: 在SQL服务器上创建SSIS包,使用BLUK插入到sql中, 在DataBase中创建存储过程以从T-SQL代码

运行该包

之后使用FTP将bluk insert的文件发送到SQL Server并调用SSIS Package usinfg存储过程