AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 83733
Accepted
Metaphor
Metaphor
Asked: 2014-11-27 09:19:51 +0800 CST2014-11-27 09:19:51 +0800 CST 2014-11-27 09:19:51 +0800 CST

Obtendo dados novos e atualizados com uma coluna de arquivo

  • 772

Estou tentando otimizar um pacote SSIS que recupera dados de uma tabela de transações muito grande que obtém milhões de novos registros diariamente. Os dados estão sendo coletados de várias centenas de servidores de campo nos quais o SQL Server 2008 Standard Edition está instalado. CDC, portanto, não pode ser usado porque é um recurso Enterprise. O plano é este:

  1. Coluna de arquivo, smallint - 0=novo (restrição padrão), 1=arquivado, 2=atualizado (acionador)
  2. Restrição padrão Arquivo=0
  3. Arquivo do acionador de atualização=2
  4. Índice no arquivo, carimbo de data/hora

O pacote SSIS irá obter todos os registros onde Archive=0, inseri-los no destino, obter todos os registros onde Archive=2 e atualizá-los no destino.

O que preciso de ajuda é a configuração da coluna Arquivo como 1 após o procedimento do SSIS terminar de gravar linhas novas ou atualizadas. Qual seria a maneira mais eficiente de definir todas as linhas processadas sem tocar em nenhuma linha que possa ter sido inserida ou atualizada após a seleção inicial?

sql-server trigger
  • 4 4 respostas
  • 1496 Views

4 respostas

  • Voted
  1. Solomon Rutzky
    2014-12-03T12:44:47+08:002014-12-03T12:44:47+08:00

    Como você está usando o SSIS e capturando as linhas alteradas, você deve fazer com que o SSIS capture os valores PK para as linhas que estão sendo processadas. A última etapa do pacote deve ser fazer uma atualização direcionada na tabela de origem, definindo o [Archive]campo como 1 com base nesses valores de PK.

    E se ainda não tiver feito, o acionador de atualização precisa excluir essas alterações da configuração do [Archive]campo como 2. Você provavelmente precisará de algo como:

    UPDATE tab
    SET    tab.[Archive] = 2
    FROM   dbo.MyTable tab
    INNER JOIN INSERTED ...
    INNER JOIN DELETED ...
    WHERE INSERTED.Archive = DELETED.Archive
    AND   DELETED.Archive IN (0, 1) -- Add 3 to this list; see below for why
    

    MAS, então você precisa lidar com o cenário em que uma linha é atualizada durante o processo ETL. Você ainda deseja ETL que muda na próxima vez. Mas se o processo ETL estiver em execução, ele mudará o [Archive]campo para 1 no final e não haverá registro dessa linha sendo alterada. Então você precisa de outro valor para indicar "Being ETLed", talvez 3. Você pode então, semelhante ao que @billinkc sugeriu em um comentário sobre a questão, faça um UPDATEcom a OUTPUTcláusula da seguinte forma:

    UPDATE TOP (@BatchSize) tab
    SET    tab.[Archive] = 3
    OUTPUT INSERTED.*
    FROM   dbo.MyTable tab
    WHERE  tab.[Archive] IN (0, 2)
    ORDER BY tab.[Archive] ASC;
    

    Então, na etapa final do pacote SSIS, a atualização de destino deve estar em ambos os valores PK AND [Archive] = 3. E adicione 3à INlista na consulta de atualização do acionador acima. Dessa forma, apenas os registros que não foram alterados durante o processo ETL serão atualizados para 1, enquanto os registros que foram alterados durante o ETL aparecerão como 2e serão selecionados novamente na próxima vez com seus valores modificados.

    Claro, você também pode querer criar um índice filtrado no [Archive]campo para suportar a obtenção de registros marcados como 0, 2 ou 3. Portanto:

    CREATE INDEX ... WHERE [Archive] IN (0, 2, 3);
    

    Você deseja obter os registros marcados como 3porque, supondo que seja um thread único por servidor de campo, os registros marcados como 3representam registros travados devido a um processo anterior que falhou. É também por isso que você não deseja marcar os registros como quando 1os UPDATE...OUTPUTobteve inicialmente; se o processo falhar, eles serão marcados como já arquivados e não serão recuperados.


    Dito isso, talvez seja melhor usar uma tabela de filas em vez de um campo de status. Você pode criar uma tabela simples com apenas alguns campos:

    QueueID BIGINT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
    MyTablePKfield  INT NOT NULL,
    CreateDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
    

    Em seguida, o gatilho se torna um INSERT, UPDATEgatilho simples que apenas faz:

    INSERT INTO dbo.MyTableEtlQueue (PKfield)
      SELECT ins.PKfield
      FROM   INSERTED ins;
    

    Em seguida, o processo SSIS obtém os valores por meio de:

    SELECT TOP (@BatchSize) etl.QueueID, tab.field1, tab.field2...
    FROM   dbo.MyTableEtlQueue etl
    INNER JOIN dbo.MyTable tab
            ON tab.PKfield = etl.MyTablePKfield
    ORDER BY etl.QueueID ASC;
    

    E o final do processo SSIS faz uma exclusão simples na [MyTableEtlQueue]tabela com base nos [QueueID]valores extraídos no início.

    Nesse modelo, você não precisa do índice filtrado ou da coluna de status em uma tabela grande, o que reduz a contenção e o tamanho dessa tabela já grande. Você não precisa se preocupar com registros em trânsito, seja em termos de atualizações ou falhas de processo.

    EDIT:
    Dada a nova informação da tabela de origem que não possui exclusividade, isso requer apenas uma pequena alteração neste método da tabela de filas: em vez de rastrear apenas o PKfield (que aparentemente não existe ;-), rastreie todos os campos ( ou pelo menos tudo o que precisa ser ETLed).

    Portanto, a tabela de filas muda para:

    QueueID BIGINT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
    MyTableField1  INT NOT NULL,
    MyTableField2  INT NOT NULL,
    ...
    MyTableFieldN  INT NOT NULL,
    CreateDate DATETIME NOT NULL DEFAULT (GETDATE()) -- or GETUTCDATE()
    

    E o gatilho muda para:

    INSERT INTO dbo.MyTableEtlQueue (PKfield)
      SELECT ins.MyTableField1, ins.MyTableField2, ..., ins.MyTableField1N
      FROM   INSERTED ins;
    

    Em seguida, o processo SSIS muda para ser (observe a falta de JOIN na tabela de origem agora):

    SELECT TOP (@BatchSize) etl.QueueID, etl.MyTableField1, etl.MyTableField2, ...
    FROM   dbo.MyTableEtlQueue etl
    ORDER BY etl.QueueID ASC;
    

    Esse método de tabela de fila isola a tabela de origem (e seu processamento) do processo de auditoria/ETL (muito parecido com o que o CDC faz). Isso permite que seu aplicativo interaja com a tabela de origem sem problemas, e nenhuma nova coluna que ocupe mais espaço na página de dados, e nenhuma transação potencialmente longa segurando a tabela de origem enquanto o ETL processa.

    • 2
  2. Best Answer
    billinkc
    2014-12-05T07:19:22+08:002014-12-05T07:19:22+08:00

    Que tal fazer uso da mesa virtual OUTPUT ? Defina corretamente o nível de isolamento da transação (instantâneo/serializável) para que você só veja as linhas a partir do momento em que seu processo é iniciado.

    Use o seguinte para sua fonte OLE DB

    UPDATE T SET Archive = 1 OUTPUT DELETED.* FROM Table T WHERE T.Archive = 0;
    

    Isso atualiza tudo em uma boa operação atômica com um efeito colateral de gerar a saída de destino em seus buffers de fluxo de dados. Encaminhe isso para o seu destino e pronto. Agradável e arrumado

    • 2
  3. Michael Green
    2014-12-02T17:55:01+08:002014-12-02T17:55:01+08:00

    O Change Tracking (CT) e o Change Data Capture (CDC) são integrados ao SQL Server. O CT pode identificar as linhas que mudaram desde a última vez que você perguntou. O CDC pode fornecer um histórico completo de todas as alterações de dados desde a última vez que você perguntou. Ambos são facilmente manipulados a partir do SSIS.

    Não haverá necessidade de redefinir sinalizadores por linha após o processamento. O sistema lida com tudo isso por meio de tabelas ocultas adicionais especificamente para essa finalidade.

    • 1
  4. Mike Honey
    2014-12-03T20:41:16+08:002014-12-03T20:41:16+08:00

    Uma solução SSIS pura seria entregar os Fluxos de Dados para as tarefas Inserir e Atualizar nas Transformações de Cache.

    http://msdn.microsoft.com/en-us/library/bb895264.aspx

    Se eles ocorrerem em 1 fluxo de dados, você poderá enviá-los para um único cache, caso contrário, você precisará de 2.

    Em seguida, você pode testar esses Caches em Fluxos de Dados posteriores usando a transformação de Pesquisa. Eu redirecionaria todas as linhas correspondentes para descartá-las efetivamente e, em seguida, continuaria apenas com as linhas não correspondentes.

    Nota Os caches são armazenados na memória, então tente manter o conteúdo enxuto, por exemplo, apenas a(s) coluna(s) chave. Contanto que você não esgote a memória física, o desempenho do tempo de execução será muito rápido (sem E/S).

    Essa solução é provavelmente a mais simples de construir e testar, pois não precisa de código para ser implementada.

    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve