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 / 34356
Accepted
RThomas
RThomas
Asked: 2013-02-08 15:15:17 +0800 CST2013-02-08 15:15:17 +0800 CST 2013-02-08 15:15:17 +0800 CST

Maneira rápida de validar duas tabelas entre si

  • 772

Estamos fazendo um processo de ETL. Quando tudo estiver dito e feito, há um monte de tabelas que devem ser idênticas. Qual é a maneira mais rápida de verificar se essas tabelas (em dois servidores diferentes) são de fato idênticas. Estou falando de esquema e dados.

Posso fazer um hash na tabela por conta própria, como eu seria capaz de fazer em um arquivo individual ou grupo de arquivos - para comparar um com o outro. Temos comparação de dados do Red-Gate, mas como as tabelas em questão contêm milhões de linhas cada, gostaria de algo com um pouco mais de desempenho.

Uma abordagem que me intriga é esse uso criativo da declaração de união . Mas, eu gostaria de explorar a ideia de hash um pouco mais, se possível.

POSTAR RESPOSTA ATUALIZADA

Para qualquer visitante futuro... aqui está a abordagem exata que acabei tomando. Funcionou tão bem que estamos fazendo isso em todas as tabelas de cada banco de dados. Obrigado às respostas abaixo por me apontarem na direção certa.

CREATE PROCEDURE [dbo].[usp_DatabaseValidation]
    @TableName varchar(50)

AS
BEGIN

    SET NOCOUNT ON;

    -- parameter = if no table name was passed do them all, otherwise just check the one

    -- create a temp table that lists all tables in target database

    CREATE TABLE #ChkSumTargetTables ([fullname] varchar(250), [name] varchar(50), chksum int);
    INSERT INTO #ChkSumTargetTables ([fullname], [name], [chksum])
        SELECT DISTINCT
            '[MyDatabase].[' + S.name + '].['
            + T.name + ']' AS [fullname],
            T.name AS [name],
            0 AS [chksum]
        FROM MyDatabase.sys.tables T
            INNER JOIN MyDatabase.sys.schemas S ON T.schema_id = S.schema_id
        WHERE 
            T.name like IsNull(@TableName,'%');

    -- create a temp table that lists all tables in source database

    CREATE TABLE #ChkSumSourceTables ([fullname] varchar(250), [name] varchar(50), chksum int)
    INSERT INTO #ChkSumSourceTables ([fullname], [name], [chksum])
        SELECT DISTINCT
            '[MyLinkedServer].[MyDatabase].[' + S.name + '].['
            + T.name + ']' AS [fullname],
            T.name AS [name],
            0 AS [chksum]
        FROM [MyLinkedServer].[MyDatabase].sys.tables T
            INNER JOIN [MyLinkedServer].[MyDatabase].sys.schemas S ON 
            T.schema_id = S.schema_id
        WHERE
            T.name like IsNull(@TableName,'%');;

    -- build a dynamic sql statement to populate temp tables with the checksums of each table

    DECLARE @TargetStmt VARCHAR(MAX)
    SELECT  @TargetStmt = COALESCE(@TargetStmt + ';', '')
            + 'UPDATE #ChkSumTargetTables SET [chksum] = (SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM '
            + T.FullName + ') WHERE [name] = ''' + T.Name + ''''
    FROM    #ChkSumTargetTables T

    SELECT  @TargetStmt

    DECLARE @SourceStmt VARCHAR(MAX)
    SELECT  @SourceStmt = COALESCE(@SourceStmt + ';', '')
            + 'UPDATE #ChkSumSourceTables SET [chksum] = (SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM '
            + S.FullName + ') WHERE [name] = ''' + S.Name + ''''
    FROM    #ChkSumSourceTables S

    -- execute dynamic statements - populate temp tables with checksums

    EXEC (@TargetStmt);
    EXEC (@SourceStmt);

    --compare the two databases to find any checksums that are different

    SELECT  TT.FullName AS [TABLES WHOSE CHECKSUM DOES NOT MATCH]
    FROM #ChkSumTargetTables TT
    LEFT JOIN #ChkSumSourceTables ST ON TT.Name = ST.Name
    WHERE IsNull(ST.chksum,0) <> IsNull(TT.chksum,0)

    --drop the temp tables from the tempdb

    DROP TABLE #ChkSumTargetTables;
    DROP TABLE #ChkSumSourceTables;

END
sql-server sql-server-2008-r2
  • 4 4 respostas
  • 26381 Views

4 respostas

  • Voted
  1. Best Answer
    Bacon Bits
    2013-02-08T17:05:04+08:002013-02-08T17:05:04+08:00

    Aqui está o que eu fiz antes:

    (SELECT 'TableA', * FROM TableA
    EXCEPT
    SELECT 'TableA', * FROM TableB)
    UNION ALL
    (SELECT 'TableB', * FROM TableB
    EXCEPT
    SELECT 'TableB', * FROM TableA)
    

    Funcionou bem o suficiente em tabelas com cerca de 1.000.000 de linhas, mas não tenho certeza de como isso funcionaria em tabelas extremamente grandes.

    Adicionado:

    Eu executei a consulta no meu sistema que compara duas tabelas com 21 campos de tipos regulares em dois bancos de dados diferentes anexados ao mesmo servidor executando o SQL Server 2005. A tabela tem cerca de 3 milhões de linhas e há cerca de 25.000 linhas diferentes. A chave primária na tabela é estranha, no entanto, pois é uma chave composta de 10 campos (é uma tabela de auditoria).

    Os planos de execução das consultas tem um custo total de 184,25879 para UNIONe 184,22983 para UNION ALL. O custo da árvore difere apenas na última etapa antes de retornar as linhas, a concatenação.

    Na verdade, a execução de qualquer consulta leva cerca de 42s mais cerca de 3s para realmente transmitir as linhas. O tempo entre as duas consultas é idêntico.

    Segunda adição:

    Na verdade, isso é extremamente rápido, cada um rodando contra 3 milhões de linhas em cerca de 2,5s:

    SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA
    
    SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB
    

    Se os resultados não corresponderem, você sabe que as tabelas são diferentes. No entanto, se os resultados corresponderem, não há garantia de que as tabelas sejam idênticas devido à chance [altamente improvável] de colisões de soma de verificação.

    Não tenho certeza de como as alterações de tipo de dados entre tabelas afetariam esse cálculo. Eu executaria a consulta nas systemvisualizações ou information_schemavisualizações.

    Eu tentei a consulta em outra tabela com 5 milhões de linhas e essa foi executada em cerca de 5s, então parece ser em grande parte O(n).

    • 19
  2. Mark Davidson
    2013-02-09T06:28:01+08:002013-02-09T06:28:01+08:00

    Aqui estão várias ideias que podem ajudar:

    1. Experimente uma ferramenta de comparação de dados diferente - você já experimentou o conjunto de ferramentas de comparação de SQL do Idera ou o ApexSQL Data Diff . Percebo que você já pagou pelo RG, mas ainda pode usá-los no modo de teste para fazer o trabalho;).

    2. Dividir e conquistar - que tal dividir as tabelas em 10 tabelas menores que podem ser manipuladas por alguma ferramenta comercial de comparação de dados?

    3. Limite-se apenas a algumas colunas - você realmente precisa comparar dados em todas as colunas?

    • 8
  3. TelegraphOperator
    2013-02-08T18:00:50+08:002013-02-08T18:00:50+08:00

    Acredito que você deve investigar BINARY_CHECKSUM, embora eu opte pela ferramenta Red Gate:

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

    Algo assim:

    SELECT BINARY_CHECKSUM(*) from myTable;
    
    • 7
  4. ErikE
    2013-02-09T21:26:12+08:002013-02-09T21:26:12+08:00

    Se você tiver uma chave primária, às vezes essa é uma maneira melhor de examinar as diferenças porque as linhas que devem ser iguais são mostradas juntas.

    SELECT
       ID = IsNull(A.ID, B.ID),
       AValue = A.Value,
       BValue = B.Value
    FROM
       dbo.TableA A
       FULL JOIN dbo.TableB B
          ON A.ID = B.ID
    WHERE
       EXISTS (
          SELECT A.*
          EXCEPT SELECT B.*
       );
    

    Veja em um sqlfiddle .

    • 3

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

    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

    Conceder acesso a todas as tabelas para um usuário

    • 5 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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