Best Practices SSIS 2008 for Starters A Fast Introduction By @Tiago Palhota tiago.palhota@gmail.com
Index Design - Anotações - Containers - Expressões - Mapping de colunas Performance - SELECT * / Table View - FastParse - Componentes Síncronos vs Componentes Assíncronos - Dicas adicionais Software adicional
Design - Anotações Perceber o contexto das tarefas a executar Ajuda a fazer debugging Relembrar o próprio criador do package do que foi feito
Design - Anotações ( Exemplo )
Design - Containers Containers podem ser definidos como um grupo de trabalho. Vantagens: Separação da execução de tasks Transacções - All or nothing
Design - Containers ( Exemplo )
Design - Expressões Úteis para tornar valores dinâmicos Uteis para criar queries dinâmicas Não usar na propriedade de Disable das taks. Usar em vez disso nas precedências ( Visibilidade )
Design - Mapping Columns Utilizar SEMPRE o mesmo nome dos campos estão nas Destinations
Performance - Select * Tamanho do Buffer Tamanho estimado por Linha = SUM(MAXSIZE(EachColumn)) Default BufferSize = 100MB Menos colunas = Mais Linhas por Buffer Menos Buffers = Maior Performance Solução? Usar apenas as colunas necessárias
FastParse Prevenir que dados incorrectos sejam passados pelo data Flow Default = False Usado nos tipos de dados NUMERIC / DATETIME Quebra de performance na ordem dos 15-35% Usar apenas quando os dados provém de origem fiável
FastParse
Performance - Componentes Síncronos vs Componentes Assíncronos
Performance - Componentes Síncronos vs Componentes Assíncronos Componentes Síncronos: Processamento linha a linha Podem criar novas colunas no buffer Não criam novas linhas ( 1:1 ) Reutilização de Buffer Exemplos : Derived Column / Multicast / Data Conversion
Performance - Componentes Síncronos vs Componentes Assíncronos Componentes Assíncronos: Divide-se em Blocagem Parcial - union all, merge, merge join,etc Blocagem total - sort, aggregate,etc Input <> Output 1:M Alocação de um buffer novo Todas as sources são assíncronas
Dicas adicionais Ordenar na Source ( ORDER BY + propriedade issorted = True) Agregações na Source Joins na Source Evitar casts desnecessários( Exemplo flat files c/ definição de dados na source ) Utilização de Transacções Escolha inteligente de dataypes de forma a reduzir a quantidade de memória necessária. Utilizar Ficheiros de Configuração
Software Adicional PoorSQL Formatter ( http://poorsql.com/ ) Bids Helper ( http://bidshelper.codeplex.com/ )
Grandes amigos! declare @data_inicio as datetime; declare @data_fim as datetime; set @data_inicio = datediff(mm, -1, getdate()); set @data_fim = getdate(); SELECT BD.id AS [Cod Teleperformance], S.sponsor_BD AS [TP DB], id_campanha as [ID Campanha], BD.dataload as [Dataload], CASE BD.STATUS WHEN 1 THEN CASE termination_status_desc WHEN 'Trunk line overflow' THEN 'Dados Errados' WHEN 'Handled' THEN CASE descricao_cu WHEN 'CU_NEG' THEN 'Não interessado' WHEN 'CU' THEN 'Interessado' ELSE CASE T.name WHEN '4' THEN 'Agendamento' WHEN '5' THEN 'Agendamento sem atendimento' WHEN '6' THEN 'Agendamento sem atendimento' WHEN 'M' THEN 'Agendamento' WHEN 'J' THEN 'Não interessado' WHEN 'Z' THEN 'Não interessado' WHEN 'S' THEN 'Inelegível invalidez' WHEN 'W' THEN 'Inelegível invalidez' WHEN 'Y' THEN 'Inelegível invalidez' WHEN 'T' THEN 'Indisponível no Horário da campanha' WHEN 'E' THEN 'Dados Errados' WHEN 'U' THEN 'Não quer responder' WHEN 'I' THEN 'Inelegível idade' WHEN 'Q' THEN 'Outras' ELSE isnull(resultado_desc, '') END END WHEN 'Nuisance' THEN 'Indisponível no Horário da campanha' WHEN 'Busy' THEN 'Indisponível no Horário da campanha' WHEN 'No Answer' THEN 'Indisponível no Horário da campanha' WHEN 'Invalid Number' THEN 'Dados Errados' WHEN 'Rejected' THEN 'Dados Errados' ELSE isnull(termination_status_desc, '') END WHEN 18 THEN 'Inelegível idade' WHEN 19 THEN 'Inelegível idade' WHEN 50 THEN 'Dados Errados' WHEN 13 THEN 'Outras' WHEN 17 THEN 'Outras' WHEN 10 THEN CASE [Tp_clientes_Metlife_Out].[dbo].GetRepeatBD(BD.id,BD.in_telefone,S.sponsor_BD) WHEN 0 THEN 'Repeated between Campaigns' ELSE 'Repeated Value' END WHEN 11 THEN CASE [Tp_clientes_Metlife_Out]. [dbo].getrepeatbd(bd.id,bd.in_telefone,s.sponsor_bd) WHEN 0 THEN 'Repeated between Campaigns' ELSE 'Repeated Value' END WHEN 16 THEN CASE [Tp_clientes_Metlife_Out]. [dbo].getrepeatbd(bd.id,bd.in_telefone,s.sponsor_bd) WHEN 0 THEN 'Repeated between Campaigns' ELSE 'Repeated Value' END ELSE isnull(bd.erro, '') END AS [Resultado], CASE descricao_cu WHEN 'CU_NEG' THEN resultado_desc END AS [Motivo n/ Interessado], T.[start_time] AS [Data de Contacto], BD.in_telefone AS [Telefone1], isnull(bd.in_telefone2, BD.in_telemovel) AS [Telefone2], [Tp_clientes_Metlife_Out]. [dbo].firstname(replace(upper(bd.in_nome), '"', '')) AS [Nome], [Tp_clientes_Metlife_Out]. [dbo].lastname(replace(upper(bd.in_nome), '"', ''), 100) AS [Apelido], BD.in_email AS [email], DATEDIFF(year, BD.in_data_nasc, @data_fim) - CASE WHEN DATEADD(yy, DATEDIFF(yy, BD.in_data_nasc, @data_fim), BD.in_data_nasc) > @data_fim THEN 1 ELSE 0 END as [Idade], BD.in_data_nasc AS [Data de Nascimento], BD.dataload AS [Data de chegada do registo], 'TLP' + RIGHT(REPLICATE('0', 10) + cast(t.easycode as varchar), 10) as [Lead Number], CASE T.STATUS WHEN 3 THEN isnull(t.moment, dateadd(second, T.duracao_seg, T.start_time)) END AS [Data de fecho da Lead], BD.in_passatempo as [URL Origem] FROM [Tp_clientes_Metlife_Out].[dbo].BD_mlife_coreg AS BD LEFT JOIN ( SELECT T.id_registo, T.[start_time], T.[usr_name], T.[termination_status], T.[easycode], T.[status], T.[moment], T.[name], T.[codigo_bd], cast(t.[duration] AS INT) / 10 AS duracao_seg, D.[descricao_aig_code] AS termination_status_desc, R.descricao_aig_code AS resultado_desc, descricao_cu FROM [Tp_clientes_Metlife_Out].[dbo]. [TMP_Diario_Tentativas] AS T INNER JOIN ( SELECT easycode, max(start_time) AS start_time FROM [Tp_clientes_Metlife_Out].[dbo].[TMP_Diario_Tentativas] WHERE start_time BETWEEN DATEADD(dd, DATEDIFF(dd, 0, @data_inicio), 0) AND DATEADD(ms, -3, DATEADD(day, DATEDIFF(day, 0, @data_fim), 1)) GROUP BY easycode ) TU ON T.easycode = TU.easycode AND T.start_time = TU.start_time LEFT JOIN [Tp_clientes_Metlife_Out].[dbo]. [PAR_StatusTerminationCallOutcomeCode] AS D ON T.termination_status = D.TP_code LEFT JOIN [Tp_clientes_Metlife_Out].[dbo].[PAR_StatusOutcomeCode] AS R ON T.NAME = R.TP_code ) AS T ON BD.id = T.id_registo AND BD.codigo_bd = T.codigo_bd INNER JOIN [Tp_clientes_Metlife_Out].[dbo].[PAR_BD_CARREGADA] C ON C.id = BD.codigo_bd INNER JOIN [Tp_clientes_Metlife_Out].[dbo].[PAR_SPONSOR_BD] S ON S.id = C.id_sponsor_bd WHERE ISNULL([start_time], BD.dataload) BETWEEN DATEADD(dd, DATEDIFF(dd, 0, @data_inicio), 0) AND DATEADD(ms, -3, DATEADD(day, DATEDIFF(day, 0, @data_fim), 1));
Friends Again! DECLARE @data_inicio AS DATETIME; DECLARE @data_fim AS DATETIME; SET @data_inicio = datediff(mm, - 1, getdate()); SET @data_fim = getdate(); SELECT BD.id AS [Cod Teleperformance], S.sponsor_BD AS [TP DB], id_campanha AS [ID Campanha], BD.dataload AS [Dataload], CASE BD.STATUS WHEN 1 THEN CASE termination_status_desc WHEN 'Trunk line overflow' THEN 'Dados Errados' WHEN 'Handled' THEN CASE descricao_cu WHEN 'CU_NEG' THEN 'Não interessado' WHEN 'CU' THEN 'Interessado' ELSE CASE T.NAME END AS [Idade], BD.in_data_nasc AS [Data de Nascimento], BD.dataload AS [Data de chegada do registo], 'TLP' + RIGHT(REPLICATE('0', 10) + cast(t.easycode AS VARCHAR), 10) AS [Lead Number], CASE T.STATUS WHEN 3 THEN isnull(t.moment, dateadd(second, T.duracao_seg, T.start_time)) END AS [Data de fecho da Lead], BD.in_passatempo AS [URL Origem] FROM [Tp_clientes_Metlife_Out].[dbo].BD_mlife_coreg AS BD L D.[descricao_aig_code] AS termination_status_desc, R.descricao_aig_code AS resultado_desc, descricao_cu GROUP BY easycode ) TU ON T.easycode = TU.easycode AND T.start_time = TU.start_time LEFT JOIN [Tp_clientes_Metlife_Out].[dbo].[PAR_StatusTerminationCallOutcomeCode] AS D ON T.termination_status = D.TP_code LEFT JOIN [Tp_clientes_Metlife_Out].[dbo].[PAR_StatusOutcomeCode] AS R ON T.NAME = R.TP_code ) AS T ON BD.id = T.id_registo (...)
Bids Helper
Dúvidas / Sugestões?
Best Practices SSIS 2008 for Starters Obrigado!