【问题标题】:SQL Server BULK INSERT of Over 1 Million rows - Need Performance ImprovementSQL Server BULK INSERT 超过 100 万行 - 需要改进性能
【发布时间】:2014-09-13 13:53:36
【问题描述】:

我的任务是开发一种将具有 100 万行或更多行的文本文件导入表格的方法。表中的每一行都是 856 字节,分成大约 150 个数据“列”。我正在使用 SQL Server 2012 标准版。与 INSERT 相关的活动是数据库上的唯一活动。我已经构建了一个执行以下操作的存储过程:

GET LIST OF UNIMPORTED DATA FILES IN A SPECIFIC DIRECTORY
LOOP THROUGH LIST OF FILES
    BULK INSERT INDIVIDUAL FILE DATA INTO (DISK-BASED) TEMP TABLE
    LOOP THROUGH RECORD-LEVEL DATA IN TEMP TABLE
    PARSE/WRITE RECORD-LEVEL DATA TO DETAILRECORD TABLE
    IF ALL RECORDS FOR A GIVEN FILE ARE SUCCESSFULLY WRITTEN TO THE DETAIL RECORD TABLE
        THEN 
            MOVE FILE TO IMPORTED_FILES DIRECTORY
            WRITE SUCESS RECORD TO IMPORTLOG TABLE
        ELSE
            WRITE FAIL RECORD TO IMPORTLOG TABLE
            MOVE ON TO NEXT FILE

将原始文本文件批量插入到 TEMP TABLE 中的速度足够快,不到 1 分钟。但是,我需要解析该原始数据并将数据放入其目标表中。需要明确的是,这意味着,例如,来自行位置 1-10 的数据应该写入目标表中,11-13 应该写入目标表中,等等。我正在使用 WHILE 循环来执行此操作而不是 CURSOR 并遍历 100 万行中的每一行,然后将原始数据作为参数传递给另一个存储过程,然后解析原始数据并插入到目标表中。我只是通过使用 SUBSTRING 函数来解析原始数据,即 SUBSTRING(@rawdata,1,10)。 正如我所提到的,每行中大约有 150 个字段。然而,解析/写入步骤的性能很糟糕。导入 170K 行需要 10 个小时。

目标表上没有聚集索引。恢复模式设置为简单。我启用了“即时文件初始化”。

我正在考虑可能使用 SSIS,但 1) 我怀疑性能可能不会快多少,并且 2) 在 SSIS 中进行故障排除似乎更麻烦。

寻找我忽略的想法、绝妙的想法和明显的建议。

编辑(在 WHILE 循环中添加代码):

WHILE @RecordCounter <= @FileRecordCount
BEGIN
    SELECT @Record = record FROM CDR.tempFile WHERE id = @RecordCounter                                 

    EXEC [CDR].[usp_ImportCDRData_Record] @pRecord = @Record, @pCarrier = @carrier, @pLogid = @ImportLogID

    SET @RecordCounter = @RecordCounter + 1
END

--Inside [CDR].[usp_ImportCDRData_Record] 

INSERT INTO dbo.DetailRecord
    ( 
    LOGID ,
    ACCOUNTNUMBER ,
    CORPID ,
    SERVICELOCATION ,
    NETWORKINDICATOR ,
    ...
    )
VALUES
    ( 
    @pLogID,
    SUBSTRING(@pRecord, 1,10), -- ACCOUNTNUMBER
    SUBSTRING(@pRecord, 11,8), -- CORPID
    SUBSTRING(@pRecord, 19,8), -- SERVICELOCATION
    SUBSTRING(@pRecord, 27,1), -- NETWORKINDICATOR
    ...
    )

【问题讨论】:

  • 这似乎很适合 ETL 工具,而不是尝试完全在 T-SQL 中完成。我没有使用过 SSIS,但它在 Talend 中非常简单。
  • CLR 是您复杂拆分的一种可能解决方案。您是否有理由循环执行任务?
  • 投票转至dba.stackexchange.com
  • 当需要一次解析 1 行并插入目标表时,除了循环之外,我还有哪些其他选项?而且,CLR 不是我的专业领域。
  • 我认为 SSIS 会快得多,因为在应用程序代码中解析比在 T-SQL 中更有效。我希望 SSIS 可以在几分钟(或几秒钟)内导入 17 万条记录,而不是几小时。

标签: sql sql-server database transactions bulkinsert


【解决方案1】:

与其使用 WHILE 循环,不如考虑一个基于集合的解决方案,您不必单独处理每一行。

如果您可以分享更多信息,WHILE 循环中有哪些代码,我们或许可以大大加快它的速度。即使不使用 SSIS ;-)

目前我不同意“需要”一次解析一行...

【讨论】:

  • 通过消除循环,我能够将文本文件中 130 万条记录的导入时间缩短到 50 秒。确实不需要 WHILE 循环,因为我只是在“集合”级别对数据进行了解析/拆分。换句话说,我现在在 [CDR].[usp_ImportCDRData_Record] 中只有 1 个 INSERT 语句,它对临时表中的所有记录进行解析/拆分并将它们插入到 DetailRecord 表中。感谢您让我从基于集合的方法来看待问题。
  • 10hrs for 170k rows with a loop vs. 50sec for 130000 rows with a set based solution -> 这是为什么循环(无论是 CURSOR 还是 WHILE)应该替换为的最佳示例之一基于集合的解决方案!
猜你喜欢
  • 2019-08-11
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多