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 / 203957
Accepted
Dharmedra Keshari
Dharmedra Keshari
Asked: 2018-04-15 04:19:47 +0800 CST2018-04-15 04:19:47 +0800 CST 2018-04-15 04:19:47 +0800 CST

Qual é a maneira mais rápida de limpar dados?

  • 772

Cenário:

Temos duas tabelas Tbl1e Tbl2no Servidor do Assinante. O Tbl1está sendo replicado do Publisher Server Ae possui dois gatilhos - inserir e atualizar. Os gatilhos estão inserindo e atualizando os dados em arquivos Tbl2.

Agora, temos que limpar (aprox. 900 milhões de registros) dos Tbl2quais tem um total de 1.000+ milhões de registros. Abaixo está a distribuição de dados de um mês a um minuto.

  • Um mês - 14986826 linhas
  • Um dia - 483446 linhas
  • Uma hora - 20143 linhas
  • Um minuto - 335 linhas

O que estou procurando;

A maneira mais rápida de limpar esses dados sem nenhum problema de produção, consistência de dados e possivelmente sem tempo de inatividade. Então, estou pensando em seguir os passos abaixo, mas preso :(

Passos:

  1. BCP Retirar os dados necessários da tabela Tbl2 existente (cerca de 100 milhões de registros, pode demorar aprox. 30 minutos).
    • Vamos supor que eu comecei a fazer a atividade em 1Fab2018 22:00, ela terminou em 1Fab2018 22:30. Quando a atividade for concluída, a tabela Tbl2 obterá novos registros que se tornarão delta
  2. Crie uma nova tabela no banco de dados com o nome Tbl3
  3. BCP nos dados exportados para a tabela recém-criada Tbl3 (cerca de 100 milhões de registros, pode levar aprox. 30 minutos)
  4. Parar o trabalho de replicação
  5. Depois que o BCP-in for concluído, use o script tsql para inserir os novos dados delta.

  6. O desafio é - Como lidar com a declaração de “atualização” do delta?

  7. Iniciar a replicação

Pergunta adicional:

Qual é a melhor maneira de lidar com o cenário?

sql-server trigger
  • 1 1 respostas
  • 13675 Views

1 respostas

  • Voted
  1. Best Answer
    Hannah Vernon
    2018-04-15T06:50:06+08:002018-04-15T06:50:06+08:00

    Como você está excluindo 90% das linhas, recomendo copiar as linhas que você precisa manter em uma nova tabela com a mesma estrutura, usar ALTER TABLE ... SWITCHpara substituir a tabela existente pela nova tabela e simplesmente descartar a tabela antiga. Consulte esta página do Microsoft Docs para obter a sintaxe.

    Um banco de ensaio simples, sem replicação que mostra o princípio geral:

    Primeiro, vamos criar um banco de dados para nosso teste:

    USE master;
    IF (SELECT 1 FROM sys.databases d WHERE d.name = 'SwitchTest') IS NOT NULL
    BEGIN
        ALTER DATABASE SwitchTest SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
        DROP DATABASE SwitchTest;
    END
    CREATE DATABASE SwitchTest;
    ALTER DATABASE SwitchTest SET RECOVERY FULL;
    BACKUP DATABASE SwitchTest TO DISK = 'NUL:';
    GO
    

    Aqui, criamos algumas tabelas, com um gatilho para mover linhas da tabela "A" para "B", aproximando sua configuração.

    USE SwitchTest;
    GO
    CREATE TABLE dbo.A
    (
        i int NOT NULL 
            CONSTRAINT PK_A
            PRIMARY KEY CLUSTERED
            IDENTITY(1,1)
        , d varchar(300) NOT NULL
        , rowdate datetime NOT NULL
    ) ON [PRIMARY]
    WITH (DATA_COMPRESSION = PAGE);
    
    CREATE TABLE dbo.B
    (
        i int NOT NULL 
            CONSTRAINT PK_B
            PRIMARY KEY CLUSTERED
        , d varchar(300) NOT NULL
        , rowdate datetime NOT NULL
    ) ON [PRIMARY]
    WITH (DATA_COMPRESSION = PAGE);
    
    GO
    CREATE TRIGGER t_a
    ON dbo.A
    AFTER INSERT, UPDATE
    AS
    BEGIN
        SET NOCOUNT ON;
        DELETE
        FROM dbo.B
        FROM dbo.B b
            INNER JOIN deleted d ON b.i = d.i
        INSERT INTO dbo.B (i, d, rowdate)
        SELECT i.i
            , i.d
            , i.rowdate
        FROM inserted i;
    END
    GO
    

    Aqui, inserimos 1.000.000 de linhas em "A" e, por causa do gatilho, essas linhas também serão inseridas em "B".

    ;WITH src AS (
        SELECT i.n
        FROM (VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9))i(n)
    )
    INSERT INTO dbo.A (d, rowdate)
    SELECT d = CRYPT_GEN_RANDOM(300), DATEADD(SECOND, s6.n + (s5.n * 100000) + (s4.n * 10000) + (s3.n * 1000) + (s2.n * 100) + (s1.n * 10), '2017-01-01T00:00:00.000')
    FROM src s1
        CROSS JOIN src s2
        CROSS JOIN src s3
        CROSS JOIN src s4
        CROSS JOIN src s5
        CROSS JOIN src s6;
    

    Limpe o log de transações, para evitar ficar sem espaço. NÃO EXECUTE isso em produção, pois ele envia os dados do log de transações para o dispositivo "NUL".

    BACKUP LOG SwitchTest TO DISK = 'NUL:';
    GO
    

    Esse código cria uma transação para garantir que nenhuma das tabelas afetadas possa ser gravada enquanto migramos as linhas:

    BEGIN TRANSACTION
    EXEC sys.sp_getapplock @Resource = N'TableSwitcher', @LockMode = 'Exclusive', @LockOwner = 'Transaction', @LockTimeout = '1000', @DbPrincipal = N'dbo';
    BEGIN TRY
        -- create a table to hold the rows we want to keep
        CREATE TABLE dbo.C
        (
            i int NOT NULL 
                CONSTRAINT PK_C
                PRIMARY KEY CLUSTERED
            , d varchar(300) NOT NULL
            , rowdate datetime NOT NULL
        ) ON [PRIMARY]
        WITH (DATA_COMPRESSION = PAGE);
    
        --copy the rows we want to keep into "C"
        INSERT INTO dbo.C (i, d, rowdate)
        SELECT b.i
            , b.d
            , b.rowdate
        FROM dbo.B
        WHERE b.rowdate >= '2017-01-11T10:00:00';
    
        --truncate the entire "B" table
        TRUNCATE TABLE dbo.B;
    
        --"switch" table "C" into "B"
        ALTER TABLE dbo.C SWITCH TO dbo.B;
    
        --drop table "C", since we no longer need it
        DROP TABLE dbo.C;
    
        --shows the count of rows in "B" which were retained.
        SELECT COUNT(1)
        FROM dbo.B
        WHERE b.rowdate >= '2017-01-11T10:00:00';
    
       --look for rows in "B" that should no longer exist.
        SELECT COUNT(1)
        FROM dbo.B
        WHERE b.rowdate < '2017-01-11T10:00:00';
    
        --release the applock and commit the transaction
        EXEC sys.sp_releaseapplock @Resource = N'TableSwitcher', @LockOwner = 'Transaction', @DbPrincipal = N'dbo';
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
        DECLARE @message nvarchar(1000) = ERROR_MESSAGE();
        DECLARE @severity int = ERROR_SEVERITY();
        DECLARE @state int = ERROR_STATE();
        RAISERROR (@message, @severity, @state);
        EXEC sys.sp_releaseapplock @Resource = N'TableSwitcher', @LockOwner = 'Transaction', @DbPrincipal = N'dbo';
        ROLLBACK TRANSACTION;
    END CATCH
    GO
    

    O sp_getapplocke sp_releaseapplockimpedem que várias instâncias desse código sejam executadas ao mesmo tempo. Isso seria útil se você habilitasse esse código para ser reutilizado por meio de uma GUI.

    (Observe que os bloqueios de aplicativos só são eficazes se todos os processos que acessam o recurso implementarem explicitamente a mesma lógica de bloqueio manual de recursos - não há mágica que "bloqueie" a tabela da mesma maneira que o SQL Server bloqueia automaticamente linhas, páginas etc. operação de inserção/atualização.)

    Agora, testamos o processo de inserção de linhas em "A", para garantir que elas sejam inseridas em "B" pelo gatilho.

    INSERT INTO dbo.A (d, rowdate)
    VALUES ('testRow', GETDATE());
    
    SELECT *
    FROM dbo.B
    WHERE B.d = 'testRow'
    
    +---------+---------+-------------------------+
    | eu | d | data de desempate |
    +---------+---------+-------------------------+
    | 1000001 | testeRow | 13-04-2018 03:49:53.343 |
    +---------+---------+-------------------------+
    
    • 26

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