2014-09-13 106 views
2

我的任務是開發一種將具有100萬或更多行的文本文件導入到表中的方法。表格中的每行都是856字節,分成大約150個「列」數據。我正在使用SQL Server 2012標準版。與INSERT相關的活動是數據庫上的唯一活動。我建立了一個存儲過程執行以下操作:超過100萬行的SQL Server BULK 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 

原始文本文件到臨時表的BULK INSERT是速度不夠快,在不到1分鐘。但是,我需要分析原始數據並將數據放入目標表中。清楚地說,這意味着,例如,應將來自行位置1-10的數據寫入目標表中,將11-13寫入目標表中,等等。我通過使用WHILE循環而不是CURSOR並遍歷100萬行中的每一行,然後將原始數據作爲參數傳遞給另一個存儲過程,然後解析原始數據並插入到目標表中。我只是通過使用SUBSTRING函數,即SUBSTRING(@ rawdata,1,10)來解析原始數據。正如我所提到的,每行中大約有150個字段。但是,解析/寫入步驟的性能很糟糕。進口170K行花費了10個小時。

目標表上沒有聚集索引。恢復模式設置爲SIMPLE。我已啓用「即時文件初始化」。

我在尋找可能使用SSIS,但1)我懷疑性能可能不會更快,並且2)SSIS中疑難解答似乎更麻煩。

尋找想法,出色的想法和我忽略的明顯建議。

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 
    ... 
    ) 
+0

這似乎是一個非常適合的ETL工具,而不是試圖完全在T-SQL中完成。我沒有使用過SSIS,但是在Talend中這將是相當微不足道的。 – ydaetskcoR 2014-09-13 13:56:26

+0

CLR是解決複雜分裂的一種可能的解決方案。你是否有理由在循環中完成任務? – u07ch 2014-09-13 14:09:03

+0

投票移動到http://dba.stackexchange.com/ – Mihai 2014-09-13 14:13:51

回答

4

使用while循環想想基於集合的解決方案,你不必單獨對待每一個單列代替:

EDIT(while循環中添加的代碼)。

如果你可以分享一些更多的信息WHILE循環中的代碼,我們可能會加快它的速度。即使不使用SSIS ;-)

目前,我都不同意有一個「需要」在一個時間來解析一行...

+0

通過消除循環,我可以將文本文件中的130萬條記錄的進口時間減少到50秒。 WHILE循環確實沒有必要,因爲我只是在「設置」級別對數據進行解析/分割。換句話說,我現在在[CDR]。[usp_ImportCDRData_Record]中只有1條INSERT語句,它對temp表中的所有記錄執行解析/拆分操作,並將它們插入到DetailRecord表中。感謝讓我從基於集合的方法來看問題。 – DMill 2014-09-13 18:04:46

+2

對於循環170k行10小時而對1爲50秒。300萬行的基於集合的解決方案 - >這是爲什麼循環(不管CURSOR或WHILE)應該用基於集合的解決方案取代的最好例子之一! – Lmu92 2014-09-13 18:23:51