SQL Server массовая вставка более 1 млн строк-требуется повышение производительности


Мне было поручено разработать метод для импорта текстовых файлов с 1 миллионом или более строк в таблицу. Каждая строка в таблице составляет 856 байт, разбитых примерно на 150 "столбцов" данных. Я использую SQL Server 2012 Standard Edition. Действие, связанное со вставками, является единственным действием в базе данных. Я построил хранимую процедуру, которая делает следующее:

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
Массовая вставка необработанного текстового файла во временную таблицу выполняется достаточно быстро, менее чем за 1 минуту. Однако мне нужно проанализировать эти необработанные данные и поместить их в таблицу назначения. Для ясности это означает, например, что данные из расположения строк 1-10 должны быть записаны в целевую таблицу, 11-13 должны быть записаны в целевую таблицу и т. д. Я делаю это, используя цикл WHILE вместо курсора и циклически проходя через каждую из 1 миллиона строк, а затем передавая необработанные данные в качестве параметра другой хранимой процедуре, которая затем анализирует необработанные данные и вставляет в целевая таблица. Я разбираю необработанные данные просто с помощью функции SUBSTRING, то есть SUBSTRING(@rawdata,1,10). И, как я уже упоминал, в каждой строке есть примерно 150 полей. Однако выполнение шага синтаксического анализа/записи ужасно. Это заняло 10 часов, чтобы импортировать 170k строк.

В целевой таблице нет кластеризованных индексов. Модель восстановления настроена на простой режим. У меня включена функция" мгновенная инициализация файла".

Я рассматриваю возможность использования SSIS, но 1) я подозреваю, что производительность не может быть намного быстрее, и 2) устранение неполадок кажется более громоздким в SSIS.

Ищу мысли, блестящие идеи и очевидные предложения, которые я пропустил.

EDIT (добавлен код внутри цикла 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
    ...
    )
1 2

1 ответ:

Вместо использования цикла WHILE подумайте о решении, основанном на множестве, где вам не нужно обрабатывать каждую строку отдельно.

Если бы вы могли поделиться некоторой дополнительной информацией о том, какой код находится в цикле WHILE, мы могли бы значительно ускорить его. Даже без использования SSIS ; -)

На данный момент я бы не согласился, что есть "необходимость" разбирать одну строку за раз...