Cách nhanh chóng để xác nhận hai bảng với nhau


12

Chúng tôi đang thực hiện một quy trình ETL. Khi tất cả được nói và thực hiện, có một loạt các bảng nên giống hệt nhau. Cách nhanh nhất để xác minh rằng các bảng đó (trên hai máy chủ khác nhau) trên thực tế là giống hệt nhau. Tôi đang nói cả lược đồ và dữ liệu.

Tôi có thể thực hiện băm trên bàn không, giống như tôi có thể vào một tệp riêng lẻ hoặc nhóm fileg - để so sánh cái này với cái kia. Chúng tôi có so sánh dữ liệu Cổng Đỏ nhưng vì các bảng trong câu hỏi chứa hàng triệu hàng mỗi nên tôi muốn một cái gì đó hiệu quả hơn một chút.

Một cách tiếp cận khiến tôi tò mò là cách sử dụng sáng tạo này của tuyên bố công đoàn . Nhưng, tôi muốn khám phá ý tưởng băm xa hơn một chút nếu có thể.

BÀI ĐĂNG CẬP NHẬT

Đối với bất kỳ khách hàng tiềm năng nào trong tương lai ... đây là cách tiếp cận chính xác mà tôi đã thực hiện. Nó hoạt động rất tốt, chúng tôi đang thực hiện nó trên mỗi bảng trong mỗi cơ sở dữ liệu. Cảm ơn câu trả lời dưới đây đã chỉ cho tôi đi đúng hướng.

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

SSIS có phải là một lựa chọn không? Nó khá dễ đọc trong một bảng và tìm kiếm bảng khác.
Kevin

1
Đó là một lựa chọn, đó là những gì đang được sử dụng cho quy trình ETL, nhưng ria mép trên lầu muốn có ý kiến ​​thứ hai về việc nó có hoạt động hay không nên sử dụng SSIS để chứng minh rằng SSIS hiểu đúng không phải là thuyết phục như bỏ những từ ưa thích như CheckSum hay Băm MD5.
RThomas

Câu trả lời:


17

Đây là những gì tôi đã làm trước đây:

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

Nó hoạt động đủ tốt trên các bảng có khoảng 1.000.000 hàng, nhưng tôi không chắc nó sẽ hoạt động tốt như thế nào trên các bảng cực lớn.

Thêm:

Tôi đã chạy truy vấn đối với hệ thống của mình, so sánh hai bảng với 21 trường loại thông thường trong hai cơ sở dữ liệu khác nhau được gắn vào cùng một máy chủ chạy SQL Server 2005. Bảng có khoảng 3 triệu hàng và có khoảng 25000 hàng khác nhau. Tuy nhiên, khóa chính trên bảng là lạ, vì đó là khóa tổng hợp của 10 trường (đó là bảng kiểm toán).

Các kế hoạch thực hiện cho các truy vấn có tổng chi phí là 184,25879 cho UNIONvà 184.22983 cho UNION ALL. Cây chi phí chỉ khác nhau ở bước cuối cùng trước khi trả lại hàng, nối.

Trên thực tế, việc thực hiện một trong hai truy vấn mất khoảng 42 giây cộng với khoảng 3 giây để thực sự truyền các hàng. Thời gian giữa hai truy vấn là giống hệt nhau.

Bổ sung thứ hai:

Điều này thực sự cực kỳ nhanh, mỗi cái chạy với 3 triệu hàng trong khoảng 2,5 giây:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB

Nếu kết quả của những kết quả không khớp, bạn biết các bảng là khác nhau. Tuy nhiên, nếu kết quả làm trận đấu, bạn đang không được bảo đảm rằng các bảng là giống hệt nhau vì [rất khó] cơ hội va chạm checksum.

Tôi không chắc chắn cách thay đổi kiểu dữ liệu giữa các bảng sẽ ảnh hưởng đến tính toán này. Tôi sẽ chạy truy vấn đối với các systemquan điểm hoặc information_schemaquan điểm.

Tôi đã thử truy vấn đối với một bảng khác có 5 triệu hàng và một hàng chạy trong khoảng 5 giây, vì vậy nó dường như chủ yếu là O (n).


1
Tại sao bạn lại đề xuất UNION thay vì UNION ALL? Những bản sao nào bạn muốn loại bỏ?
AK

@AlexKuznetsov Đủ công bằng, mặc dù tôi nghi ngờ rằng công cụ truy vấn đủ thông minh để nhận ra rằng chúng tôi đang chọn toàn bộ khóa chính hoặc có thể không xử lý phân biệt cho đến khi có kết quả được đặt từ các EXCEPTcâu lệnh. Bây giờ tôi thực sự tò mò nếu có. Mặc dù vậy, nó có ý nghĩa logic hơn đối với RDBMS, vì vậy tôi sẽ cập nhật nó.
Bacon Bits

Câu hỏi là về 2 máy chủ khác nhau mặc dù.
ypercubeᵀᴹ

Tôi không có hai máy chủ để kiểm tra. :)
Bacon Bits

Sự kết hợp giữa một cách tiếp cận máy chủ được liên kết làm tôi lo lắng. Tôi thích cách tiếp cận tổng hợp và binary_checksum ... sẽ bắt đầu một số thử nghiệm với điều đó ngay bây giờ.
RThomas

8

Dưới đây là một số ý tưởng có thể giúp:

  1. Hãy thử công cụ tìm dữ liệu khác nhau - bạn đã thử bộ công cụ so sánh SQL của Idera hoặc ApexQuery Data Diff . Tôi nhận ra rằng bạn đã trả tiền cho RG nhưng bạn vẫn có thể sử dụng những thứ này trong chế độ dùng thử để hoàn thành công việc;).

  2. Phân chia và chinh phục - làm thế nào về việc chia bảng thành 10 bảng nhỏ hơn có thể được xử lý bởi một số công cụ so sánh dữ liệu thương mại?

  3. Chỉ giới hạn bản thân trong một số cột - bạn có thực sự cần so sánh dữ liệu trong tất cả các cột không?


7

Tôi tin rằng bạn nên điều tra BINARY_CHECKSUM, mặc dù tôi sẽ chọn công cụ Red Gate:

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

Một cái gì đó như thế này:

SELECT BINARY_CHECKSUM(*) from myTable;

Điều này sẽ phát hiện sự khác biệt trong lược đồ của các bảng (tên cột hoặc kiểu dữ liệu khác nhau)?
ypercubeᵀᴹ

Điều này có tiềm năng. Tôi sẽ làm một số thử nghiệm và lấy lại.
RThomas

Đã cho bạn cộng 1, nhưng tổng số được cung cấp bởi các bit thịt xông khói là đóng băng trên đầu. Cảm ơn.
RThomas

3

Nếu bạn có khóa chính, đôi khi đây là cách tốt hơn để kiểm tra sự khác biệt bởi vì các hàng phải giống nhau được hiển thị cùng nhau.

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

Xem nó trong một sqlfiddle .


Rất vui, cảm ơn ... cách tốt để tìm sự khác biệt sau khi tổng hợp cho thấy sự khác biệt tồn tại. Cảm ơn.
RThomas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.