Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Le package SSIS fonctionne 500 fois plus longtemps sur un serveur

Si la journalisation est activée, de préférence sur SQL Server, ajoutez l'événement OnPipelineRowsSent. Vous pouvez alors déterminer où il passe tout son temps. Voir ce message Votre sous-système IO est bloqué et génère tous ces fichiers temporaires parce que vous n'êtes plus en mesure de conserver toutes les informations en mémoire (en raison de vos transformations asynchrones).

La requête pertinente de l'article lié est la suivante. Il regarde les événements dans le sysdtslog90 (Les utilisateurs de SQL Server 2008+ remplacent sysssislog ) et effectue une analyse temporelle sur eux.

;
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);

Vous avez pu utiliser cette requête pour discerner que le composant Merge Join était le composant en retard. Pourquoi il fonctionne différemment entre les deux serveurs, je ne peux pas dire à ce stade.

Si vous avez la possibilité de créer une table dans votre système de destination, vous pouvez modifier votre processus pour avoir deux 2 flux de données (et éliminer les composants asynchrones coûteux).

  1. Le premier flux de données prendrait le fichier plat et les colonnes dérivées et les placerait dans une table intermédiaire.
  2. Vous disposez alors d'une tâche d'exécution SQL pour gérer la logique Get Min Date + Delete.
  3. Ensuite, votre deuxième flux de données interroge votre table intermédiaire et l'intègre directement dans votre destination.