Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Il pacchetto SSIS viene eseguito per 500 volte più a lungo su un server

Se hai attivato la registrazione, preferibilmente a SQL Server, aggiungi l'evento OnPipelineRowsSent. È quindi possibile determinare dove sta trascorrendo tutto il suo tempo. Vedi questo post Il tuo sottosistema IO viene bloccato e genera tutti questi file temporanei perché non sei più in grado di mantenere tutte le informazioni in memoria (a causa delle tue trasformazioni asincrone).

La domanda pertinente dall'articolo collegato è la seguente. Esamina gli eventi nel sysdtslog90 (Gli utenti di SQL Server 2008+ sostituiscono sysssislog ) ed esegue alcune analisi temporali su di essi.

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

È stato possibile utilizzare questa query per discernere che il componente Unisci join era il componente in ritardo. Perché funziona in modo diverso tra i due server, non posso dirlo a questo punto.

Se hai la possibilità di creare una tabella nel tuo sistema di destinazione, puoi modificare il tuo processo per avere due flussi di dati 2 (ed eliminare i costosi componenti asincroni).

  1. Il primo flusso di dati prenderebbe le colonne File flat e Derived e le atterrerebbe in una tabella di staging.
  2. Si dispone quindi di un'attività Esegui SQL attiva per gestire la logica Ottieni data minima + Elimina.
  3. Poi hai il tuo secondo flusso di dati che esegue query dalla tabella di staging e lo inserisce direttamente nella tua destinazione.