Пакет SSIS работает на 500 раз больше на одном сервере

У меня есть пакет SSIS - две задачи потока данных, 8 компонентов каждый, чтение из двух плоских файлов, ничего впечатляющего. Если я запускаю его в BIDS, он надежно занимает около 60 секунд. У меня есть DB-сервер sandbox с пакетом, работающим в задании, которое также надежно занимает 30-60 секунд. На моем рабочем сервере одна и та же работа с одним и тем же пакетом занимает от 30 секунд до 12 часов.

При включении регистрации в пакете это похоже на то, что он боксирует вниз - сначала по крайней мере - на этапе предварительного выполнения одного или другого (или обоих) задач потока данных. Но я также могу видеть, что данные поступают медленно, в кусках, поэтому я думаю, что это происходит оттуда позже. Подсистема IO получает удар, и SSIS генерирует много больших файлов temp (около 150 МБ - мои файлы входных данных составляют всего около 24 МБ) и интенсивно читает и пишет из этих файлов (перебивает?).

Следует отметить, что если я укажу свой экземпляр BIDS пакета на рабочем сервере, ему все равно потребуется всего 60 секунд! Так что это должно быть что-то с запуском dtexec, а не с самой БД.

Я уже пытался оптимизировать свой пакет, уменьшая размер байта строки ввода, и я сделал два потока данных, которые выполнялись последовательно, а не параллельно - безрезультатно.

Оба сервера БД работают с 64-битным MSSQL 2008 R2 с одинаковым уровнем исправления. Оба сервера являются виртуальными машинами на одном и том же хосте с тем же распределением ресурсов. Нагрузка на производственный сервер не должна быть намного выше, чем на сервере песочницы прямо сейчас. Единственное различие, которое я вижу, это то, что на рабочем сервере работает Windows Server 2008, а песочница - на Windows Server 2008 R2.

Помощь!!! Любые идеи, которые нужно попробовать, приветствуются, что может вызвать такое огромное расхождение?

Приложение A

Вот мой пакет выглядит как...

Управляющий поток чрезвычайно прост:

Control Flow

Поток данных выглядит следующим образом:

Data Flow

Вторая задача потока данных точно такая же, как раз с другим исходным файлом и таблицей назначения.

Примечания

Ограничение завершения в потоке управления доступно только для того, чтобы задачи запускались последовательно, чтобы попытаться сократить ресурсы, необходимые одновременно (не то, чтобы это помогло решить проблему)... фактическая зависимость между этими двумя задачами отсутствует.

Я знаю о потенциальных проблемах с блокировкой и частично блокирующими преобразованиями (не могу сказать, что я их полностью понимаю, но, по крайней мере, несколько), и я знаю, что объединение агрегатов и слияний блокирует и может вызвать проблемы. Однако, опять же, все это выполняется отлично и быстро в любой другой среде, кроме производственного сервера... так что дает?

Причина объединения Merge заключается в том, чтобы заставить задачу ждать завершения обеих ветвей Multicast. Правильная ветвь находит минимальное время datetime во входном файле и удаляет все записи в таблице после этой даты, тогда как левая ветвь несет новые входные записи для вставки - поэтому, если правильная ветка продолжается до агрегации и удаления, новые записи будут удалите (это произошло). Я не знаю, как лучше справиться с этим.

Ошибка, выводимая из "Удалить записи", всегда пуста - это преднамеренно, поскольку на самом деле я не хочу, чтобы строки из этой ветки в слиянии (только для синхронизации было выполнено слияние, как описано выше).

См. комментарий ниже о значках предупреждений.

Ответ 1

Если вы включили ведение журнала, желательно на SQL Server, добавьте событие OnPipelineRowsSent. Затем вы можете определить, где он проводит все свое время. См. Это сообщение . Ваша подсистема ввода-вывода становится заблокированной и генерирует все эти временные файлы, потому что вы больше не можете хранить всю информацию в памяти (из-за ваши асинхронные преобразования).

Соответствующий запрос из связанной статьи следующий. Он рассматривает события в sysdtslog90 (заменители SQL Server 2008+ sysssislog) и выполняет некоторое время на них.

;
WITH PACKAGE_START AS
(
    SELECT DISTINCT
        Source
    ,   ExecutionID
    ,   Row_Number() Over (Order By StartTime) As RunNumber
    FROM
        dbo.sysdtslog90 AS L
    WHERE
        L.event = 'PackageStart'
)
, EVENTS AS
(
    SELECT
        SourceID
    ,   ExecutionID
    ,   StartTime
    ,   EndTime
    ,   Left(SubString(message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, 56) + 1) + 1) + 1) + 2, Len(message)), CharIndex(':', SubString(message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, CharIndex(':', message, 56) + 1) + 1) + 1) + 2, Len(message)) ) - 2) As DataFlowSource
    ,   Cast(Right(message, CharIndex(':', Reverse(message)) - 2) As int) As RecordCount
    FROM
        dbo.sysdtslog90 AS L
    WHERE
        L.event = 'OnPipelineRowsSent'
)
, FANCY_EVENTS AS
(
    SELECT
        SourceID
    ,   ExecutionID
    ,   DataFlowSource
    ,   Sum(RecordCount) RecordCount
    ,   Min(StartTime) StartTime
    ,   (
            Cast(Sum(RecordCount) as real) /
            Case
                When DateDiff(ms, Min(StartTime), Max(EndTime)) = 0
                    Then 1
                Else DateDiff(ms, Min(StartTime), Max(EndTime))
            End
        ) * 1000 As RecordsPerSec
    FROM
        EVENTS DF_Events
    GROUP BY
        SourceID
    ,   ExecutionID
    ,   DataFlowSource
)
SELECT
    'Run ' + Cast(RunNumber As varchar) As RunName
,   S.Source
,   DF.DataFlowSource
,   DF.RecordCount
,   DF.RecordsPerSec
,   Min(S.StartTime) StartTime
,   Max(S.EndTime) EndTime
,   DateDiff(ms, Min(S.StartTime)
,   Max(S.EndTime)) Duration
FROM
    dbo.sysdtslog90 AS S
    INNER JOIN
        PACKAGE_START P
        ON S.ExecutionID = P.ExecutionID
    LEFT OUTER JOIN
        FANCY_EVENTS DF
        ON S.SourceID = DF.SourceID
        AND S.ExecutionID = DF.ExecutionID
WHERE
    S.message <> 'Validating'
GROUP BY
    RunNumber
,   S.Source
,   DataFlowSource
,   RecordCount
,   DF.StartTime
,   RecordsPerSec
,   Case When S.Source = P.Source Then 1 Else 0 End
ORDER BY
    RunNumber
,   Case When S.Source = P.Source Then 1 Else 0 End Desc

DF.StartTime , Min (S.StartTime);

Вы смогли использовать этот запрос, чтобы понять, что компонент Merge Join является компонентом запаздывания. Почему он работает по-разному между двумя серверами, я не могу сказать в этот момент.

Если у вас есть возможность создать таблицу в вашей целевой системе, вы можете изменить свой процесс на два потока данных (и устранить дорогостоящие асинхронные компоненты).

  • Первый поток данных будет принимать столбцы Flat file и Derived и помещать их в промежуточную таблицу.
  • Затем у вас есть задача Execute SQL Task для обработки логики Get Min Date + Delete.
  • Затем у вас есть второй запрос потока данных из вашей промежуточной таблицы и привязка его прямо к месту назначения.

Ответ 2

Ниже приведенные ниже шаги помогут улучшить производительность SSIS.

  • Убедитесь, что для всех менеджеров подключений установлено значениеDelayValidation (= True).
  • Убедитесь, что для параметра ValidateExternalMetadata установлено значение false
  • DefaultBufferMaxRows и DefaultBufferSize соответствуют размерам строк таблицы
  • Использовать подсказки по мере необходимости http://technet.microsoft.com/en-us/library/ms181714.aspx