Cara cepat untuk memvalidasi dua tabel satu sama lain

12

Kami sedang melakukan proses ETL. Ketika semua dikatakan dan dilakukan ada banyak tabel yang harus identik. Apa cara tercepat untuk memverifikasi bahwa tabel tersebut (pada dua server berbeda) sebenarnya identik. Saya berbicara skema dan data.

Dapatkah saya melakukan hash di atas meja itu sendiri seperti saya akan dapat pada file atau filegroup individu - untuk membandingkan satu dengan yang lain. Kami memiliki data Red-Gate yang membandingkan, tetapi karena tabel yang dimaksud berisi jutaan baris, masing-masing saya ingin sesuatu yang sedikit lebih berkinerja.

Salah satu pendekatan yang menggelitik saya adalah penggunaan pernyataan serikat ini secara kreatif . Tapi, saya ingin mengeksplorasi ide hash sedikit lebih jauh jika memungkinkan.

PEMBARUAN JAWABAN POST

Untuk setiap pengunjung di masa depan ... inilah pendekatan tepat yang akhirnya saya ambil. Ini bekerja sangat baik kami melakukannya pada setiap tabel di setiap basis data. Terima kasih atas jawaban di bawah karena mengarahkan saya ke arah yang benar.

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
RThomas
sumber
Apakah SSIS suatu opsi? Itu akan cukup mudah dibaca di satu meja dan melakukan pencarian terhadap yang lain.
Kevin
1
Ini adalah pilihan, itu yang digunakan untuk proses ETL, tetapi kumis di lantai atas menginginkan pendapat kedua tentang apakah itu berfungsi atau tidak, jadi menggunakan SSIS untuk membuktikan bahwa SSIS benar, tidak meyakinkan seperti menjatuhkan kata-kata mewah seperti CheckSum atau MD5 Hash.
RThomas

Jawaban:

17

Inilah yang telah saya lakukan sebelumnya:

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

Ini bekerja cukup baik pada tabel yang sekitar 1.000.000 baris, tetapi saya tidak yakin seberapa baik itu akan bekerja pada tabel yang sangat besar.

Ditambahkan:

Saya telah menjalankan kueri terhadap sistem saya yang membandingkan dua tabel dengan 21 bidang tipe biasa dalam dua basis data berbeda yang dilampirkan ke server yang sama yang menjalankan SQL Server 2005. Tabel ini memiliki sekitar 3 juta baris, dan ada sekitar 25000 baris yang berbeda. Namun, kunci utama di atas meja itu aneh, karena ini adalah kunci gabungan dari 10 bidang (ini adalah tabel audit).

Paket eksekusi untuk kueri memiliki total biaya 184.25879 untuk UNIONdan 184.22983 untuk UNION ALL. Biaya pohon hanya berbeda pada langkah terakhir sebelum mengembalikan baris, rangkaian.

Sebenarnya menjalankan salah satu query membutuhkan sekitar 42s ditambah sekitar 3s untuk benar-benar mengirimkan baris. Waktu antara dua kueri identik.

Penambahan Kedua:

Ini sebenarnya sangat cepat, masing-masing berjalan melawan 3 juta baris dalam sekitar 2,5 detik:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB

Jika hasil yang tidak cocok, Anda tahu tabel berbeda. Namun, jika hasil melakukan pertandingan, Anda tidak dijamin bahwa tabel identik karena kesempatan [sangat tidak mungkin] tabrakan checksum.

Saya tidak yakin bagaimana perubahan tipe data di antara tabel akan memengaruhi perhitungan ini. Saya akan menjalankan kueri terhadap systemtampilan atau information_schematampilan.

Saya mencoba query terhadap tabel lain dengan 5 juta baris dan yang berjalan sekitar 5s, sehingga tampaknya sebagian besar O (n).

Bit Bacon
sumber
8

Berikut beberapa ide yang mungkin membantu:

  1. Coba alat data diff yang berbeda - pernahkah Anda mencoba toolset Perbandingan SQL Idera atau ApexSQL Data Diff . Saya menyadari bahwa Anda sudah membayar untuk RG tetapi Anda masih dapat menggunakan ini dalam mode percobaan untuk menyelesaikan pekerjaan;).

  2. Membagi dan menaklukkan - bagaimana dengan membagi tabel menjadi 10 tabel yang lebih kecil yang dapat ditangani oleh beberapa alat perbandingan data komersial?

  3. Batasi diri Anda hanya untuk beberapa kolom - apakah Anda benar-benar perlu membandingkan data di semua kolom?

Mark Davidson
sumber
7

Saya yakin Anda harus menyelidiki BINARY_CHECKSUM, meskipun saya akan memilih alat Gerbang Merah:

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

Sesuatu seperti ini:

SELECT BINARY_CHECKSUM(*) from myTable;
TelegraphOperator
sumber
Apakah ini akan mendeteksi perbedaan dalam skema tabel (nama kolom atau tipe data yang berbeda)?
ypercubeᵀᴹ
3

Jika Anda memiliki kunci utama, ini kadang-kadang cara yang lebih baik untuk memeriksa perbedaan karena baris yang seharusnya sama ditampilkan bersama.

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

Lihat di sqlfiddle .

ErikE
sumber