AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 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

快速验证两个表的方法

  • 772

我们正在做一个 ETL 过程。总而言之,有一堆表应该是相同的。验证这些表(在两个不同的服务器上)实际上是否相同的最快方法是什么。我说的是模式和数据。

我可以像在单个文件或文件组上那样对自己的表进行哈希处理 - 将一个与另一个进行比较。我们有 Red-Gate 数据比较,但由于相关表包含数百万行,我想要一些性能更高的东西。

一种让我感兴趣的方法是对 union 声明的创造性使用。但是,如果可能的话,我想进一步探索哈希的想法。

发布答案更新

对于任何未来的游客......这是我最终采取的确切方法。它工作得很好,我们在每个数据库的每个表上都这样做。感谢下面的答案为我指明了正确的方向。

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 个回答
  • 26381 Views

4 个回答

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

    这是我以前做过的事情:

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

    它在大约 1,000,000 行的表上运行良好,但我不确定它在超大表上的运行情况如何。

    添加:

    我已经对我的系统运行了查询,该系统比较了两个不同数据库中的两个表和 21 个常规类型的字段,这些数据库连接到运行 SQL Server 2005 的同一服务器。该表有大约 300 万行,并且大约有 25000 行不同。然而,表上的主键很奇怪,因为它是 10 个字段的复合键(它是一个审计表)。

    查询的执行计划的总成本为 184.25879UNION和 184.22983 UNION ALL。树成本仅在返回行之前的最后一步(即连接)上有所不同。

    实际上执行任一查询大约需要 42 秒加上大约 3 秒来实际传输行。两个查询之间的时间是相同的。

    第二个补充:

    这实际上非常快,每行运行 300 万行大约需要 2.5 秒:

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

    如果这些结果不匹配,您就知道这些表是不同的。但是,如果结果确实匹配,则不能保证这些表是相同的,因为校验和冲突的可能性[极不可能]。

    我不确定表之间的数据类型更改将如何影响此计算。我会针对system视图或information_schema视图运行查询。

    我尝试对另一个有 500 万行的表进行查询,并且该表在大约 5 秒内运行,所以它似乎很大程度上是 O(n)。

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

    这里有几个想法可能会有所帮助:

    1. 尝试不同的数据差异工具 - 您是否尝试过 Idera 的SQL 比较工具集或ApexSQL 数据差异。我知道您已经为 RG 支付了费用,但您仍然可以在试用模式下使用这些来完成工作;)。

    2. 分而治之 - 将表格拆分为 10 个较小的表格,这些表格可以由一些商业数据比较工具处理如何?

    3. 仅限于某些列 - 您真的需要比较所有列中的数据吗?

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

    我相信您应该调查 BINARY_CHECKSUM,尽管我会选择 Red Gate 工具:

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

    像这样的东西:

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

    如果您有主键,这有时是检查差异的更好方法,因为应该相同的行显示在一起。

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

    在 sqlfiddle 中查看它。

    • 3

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve