SSIS - 插入大量行(数百万行)的最佳方式

时间:2015-07-25 10:48:00

标签: c# sql sql-server xml ssis

所以这就是场景:我有一个XML文件,大小为500GB,数据大约有6亿行(一次在数据库表上)。我正在使用SSIS进行操作,因为如果我要使用SSIS组件(即:XML Source),它会占用大量内存,这可能会导致超时(如果我错了,请纠正我) ,但据我所知,使用SSIS上的组件将XML的内容加载到内存中 - 文件很大,肯定会导致错误)。我的方法是:

  • 使用Script Task使用XML Reader解析XML数据(到目前为止,XML Reader是最好的方法,因为它使用正向,非缓存的方法解析XML)
  • DataTable
  • 上插入数据
  • DataTable上的每500,000行,使用SqlBulkCopy将内容插入数据库,然后清除DataTable
  • 的内容

我的问题是,目前,我试图解析另一个大小为200GB的文件,并且它运行在13.5M / 1小时左右 - 而且我不知道它是否仍然没有运行时间。它确实解决了我的问题 - 但它不是太优雅,我的意思是,应该有其他方法。

我正在研究其他方法,例如:

  • 将大型XML文件分成小块CSV(大约20GB),然后使用SSIS Data Flow task
  • 每个新行使用INSERT脚本

你能帮我决定哪个最好吗?或建议任何其他解决方案。

非常感谢每一个答案。

修改

我忘了提及 - 我的方法将是动态的。我的意思是,有许多表将填充大型XML文件。因此,使用脚本组件作为源可能不太有用,因为我仍然需要定义输出列。但是,仍然会试一试。

编辑2015-07-28

该文件来自我们的客户,我们无法对他们想要发送给我们的来源做任何事情。 XML,就是这样。以下是我正在使用的XML的示例:

<?xml version="1.0" encoding="UTF-8"?>
<MFADISDCP>
  <ROW>
    <INVESTMENT_CODE>DATA</INVESTMENT_CODE>
    <DATE_OF_RECORD>DATA</DATE_OF_RECORD>
    <CAPITAL_GAIN_DISTR_RATE>DATA</CAPITAL_GAIN_DISTR_RATE>
    <INCOME_DISTR_RATE>DATA</INCOME_DISTR_RATE>
    <DISTR_PAYMENT_DATE>DATA</DISTR_PAYMENT_DATE>
    <CURRENCY>DATA</CURRENCY>
    <CONFIRM>DATA</CONFIRM>
    <EXPECTED_DISTRIBUTION_AMOUNT>DATA</EXPECTED_DISTRIBUTION_AMOUNT>
    <KEYING_STATUS>DATA</KEYING_STATUS>
    <DAF_RATE>DATA</DAF_RATE>
    <INCOME_START_DATE>DATA</INCOME_START_DATE>
    <ALLOCABLE_END_DATE>DATA</ALLOCABLE_END_DATE>
    <TRADE_DATE>DATA</TRADE_DATE>
    <OVR_CAPITAL_GAIN_DISTR_OPTION>DATA</OVR_CAPITAL_GAIN_DISTR_OPTION>
    <OVR_INCOME_DISTR_OPTION>DATA</OVR_INCOME_DISTR_OPTION>
    <BACKDATED_DISTRIBUTION>DATA</BACKDATED_DISTRIBUTION>
    <DATE_MODIFIED>DATA</DATE_MODIFIED>
  </ROW>
<!--AROUND 49M+ OF THIS ROWS-->
</MFADISDCP>

1 个答案:

答案 0 :(得分:0)

如果我这样做,那么我会将其分解为以下任务:

  1. 将XML文件转换为(制表符或逗号)分隔文件。如果您的服务器有快速磁盘(SSD),那么这应该非常快。请注意数据中可能包含可能破坏分隔符格式的特殊字符的字符串。不要使用DataTable对象,因为它很慢。您可以对此进行流式传输,这样您就不需要一次性将整个文件放在内存中(除非您的服务器有几百个内存)
  2. 截断数据库中用于加载数据的阶段表。
  3. 使用SQL Server的bcp.exe将分隔文件推送到数据库的阶段表中。这可能是将大量数据导入数据库的最快方法。这样做的一个问题是,如果它失败,那么很难找到导致失败的数据行。
  4. 删除分隔文件,因为您不需要占用大量空间。
  5. 创建一个SQL存储过程,将数据从舞台表移动到您将使用它的任何位置。
  6. 您可以为此使用SSIS脚本任务,或者您可以编写自己的独立服务。

    注意,这都是理论上的,可能有更好的方法,但这可能是一个很好的起点,并找出你的瓶颈所在。