두 테이블을 서로에 대해 검증하는 빠른 방법


13

우리는 ETL 프로세스를하고 있습니다. 모든 것이 말되고 완료되면 동일한 테이블이 많이 있습니다. 두 개의 다른 서버에있는 해당 테이블이 실제로 동일한 지 확인하는 가장 빠른 방법은 무엇입니까? 스키마와 데이터를 모두 이야기하고 있습니다.

개별 파일이나 파일 그룹에서 할 수있는 것처럼 자체적으로 테이블에서 해시를 수행 할 수 있습니까? 우리는 Red-Gate 데이터를 비교하지만 문제의 테이블에는 각각 수백만 행이 포함되어 있기 때문에 조금 더 성능이 좋은 것을 원합니다.

저를 흥미롭게 만드는 한 가지 접근법은 이러한 노동 조합 성명을 창의적으로 사용하는 것입니다 . 그러나 가능한 경우 해시 아이디어를 조금 더 탐구하고 싶습니다.

답변 업데이트

미래의 모든 vistors를 위해 ... 여기 내가 끝내는 정확한 접근법이 있습니다. 각 데이터베이스의 모든 테이블에서 잘 작동했습니다. 올바른 방향으로 나를 가리켜 주신 아래 답변에 감사드립니다.

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는 옵션입니까? 한 테이블에서 읽고 다른 테이블을 조회하는 것이 상당히 쉽습니다.
케빈

1
선택 사항이며 ETL 프로세스에 사용되는 것이지만 위층의 콧수염은 SSIS를 사용하여 SSIS를 사용하여 제대로 작동했는지 여부를 확인하기 위해 SSIS를 사용하는지 여부에 대한 두 번째 의견을 원합니다. MD5 해시.
RThomas

답변:


18

다음은 내가 한 일입니다.

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

약 1,000,000 행의 테이블에서는 충분히 잘 작동했지만 매우 큰 테이블에서는 얼마나 잘 작동하는지 잘 모르겠습니다.

추가 :

시스템에 대해 쿼리를 실행하여 SQL Server 2005를 실행하는 동일한 서버에 연결된 두 개의 서로 다른 데이터베이스에있는 21 개의 정규 유형 필드와 두 개의 테이블을 비교했습니다.이 테이블에는 약 3 백만 개의 행이 있고 약 25000 개의 행이 있습니다. 그러나 테이블의 기본 키는 10 개의 필드로 구성된 복합 키이므로 감사 테이블입니다.

쿼리 실행 계획의 총 비용은 184.25879 UNION이고 184.22983은 UNION ALL입니다. 트리 비용은 행, 연결을 반환하기 전 마지막 단계에서만 다릅니다.

실제로 쿼리를 실행하려면 실제로 행을 전송하는 데 약 42 초 + 3 초가 걸립니다. 두 쿼리 사이의 시간은 동일합니다.

두 번째 추가 :

이것은 실제로 매우 빠릅니다. 각 행은 약 2.5 초 동안 3 백만 행에 대해 실행됩니다.

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB

그 결과가 일치하지 않으면 테이블이 다르다는 것을 알 수 있습니다. 그러나 결과 일치하면 체크섬 충돌 가능성이 높기 때문에 테이블이 동일하다는 보장 이 없습니다 .

테이블 간의 데이터 유형 변경이이 계산에 어떤 영향을 미치는지 잘 모르겠습니다. system뷰 또는 information_schema뷰 에 대해 쿼리를 실행합니다 .

5 백만 개의 행이있는 다른 테이블에 대해 쿼리를 시도했지만 그 테이블은 약 5 초 동안 실행되었으므로 O (n) 인 것으로 보입니다.


8

다음은 도움이 될만한 몇 가지 아이디어입니다.

  1. 다른 데이터 diff 도구를 사용해보십시오-Idera의 SQL Comparison 도구 세트 또는 ApexSQL Data Diff 를 사용해 보셨습니까 ? 나는 당신이 이미 RG에 대한 비용을 지불했다는 것을 알고 있지만 여전히 시험 모드에서 작업을 수행 할 수 있습니다.).

  2. 나누고 정복하십시오-상용 데이터 비교 도구로 처리 할 수있는 10 개의 작은 테이블로 테이블을 분할하는 것은 어떻습니까?

  3. 일부 열로만 자신을 제한하십시오. 모든 열의 데이터를 실제로 비교해야합니까?


7

Red Gate 도구를 선택하지만 BINARY_CHECKSUM을 조사해야한다고 생각합니다.

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

이 같은:

SELECT BINARY_CHECKSUM(*) from myTable;

테이블 스키마의 차이 (다른 열 이름 또는 데이터 유형)를 감지합니까?
ypercubeᵀᴹ

@ ypercubeᵀᴹ 예, 이것을 확인할 수 있습니다. CHECKSUM_AGG(BINARY_CHECKSUM(*))체크섬이 일치하는 동일한 두 테이블 사이 의 사용을 테스트하고있었습니다 . 테이블 중 하나에 열을 추가 한 후 체크섬 값이 더 이상 동일하지 않았습니다.
Jeff Mergler

3

기본 키가있는 경우 동일한 행이 함께 표시되므로 차이를 조사하는 것이 더 좋은 방법입니다.

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에서 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.