相互验证两个表的快速方法

RTh*_*mas 15 sql-server etl sql-server-2008-r2 except

我们正在做一个 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
Run Code Online (Sandbox Code Playgroud)

Bac*_*its 19

这是我之前所做的:

(SELECT 'TableA', * FROM TableA
EXCEPT
SELECT 'TableA', * FROM TableB)
UNION ALL
(SELECT 'TableB', * FROM TableB
EXCEPT
SELECT 'TableB', * FROM TableA)
Run Code Online (Sandbox Code Playgroud)

它在大约 1,000,000 行的表上工作得很好,但我不确定它在超大表上的工作情况如何。

添加:

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

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

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

第二个补充:

这实际上非常快,每一个在大约 2.5 秒内运行 300 万行:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB
Run Code Online (Sandbox Code Playgroud)

如果这些结果不匹配,您就知道表格不同。但是,如果结果比赛,你不能保证该表是因为校验和冲突的[不大可能]的机会是相同的。

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

我尝试对另一个有 500 万行的表进行查询,该表运行了大约 5 秒,所以它似乎主要是 O(n)。


Mar*_*son 8

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

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

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

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


小智 7

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

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

像这样的东西:

SELECT BINARY_CHECKSUM(*) from myTable;
Run Code Online (Sandbox Code Playgroud)