एक दूसरे के खिलाफ दो तालिकाओं को मान्य करने का त्वरित तरीका


13

हम एक ETL प्रक्रिया कर रहे हैं। जब सब कहा जाता है और किया जाता है तो तालिकाओं का एक गुच्छा होता है जो समान होना चाहिए। यह सत्यापित करने का सबसे तेज़ तरीका क्या है कि वे टेबल (दो अलग-अलग सर्वरों पर) वास्तव में समान हैं। मैं स्कीमा और डेटा दोनों बात कर रहा हूं।

क्या मैं मेज पर एक हैश कर सकता हूं जैसे कि मैं एक व्यक्ति फ़ाइल या फ़ाइल समूह पर एक दूसरे से तुलना करने में सक्षम होऊंगा। हमारे पास रेड-गेट डेटा की तुलना है, लेकिन चूंकि तालिका में प्रश्न में लाखों पंक्तियाँ हैं, जिनमें से प्रत्येक में मुझे कुछ अधिक अच्छा प्रदर्शन करना है।

एक दृष्टिकोण जो मुझे इंटिग्रेट करता है वह है यूनियन स्टेटमेंट का यह रचनात्मक उपयोग । लेकिन, यदि संभव हो तो थोड़ा और आगे हैश विचार तलाशना चाहूंगा।

सबसे पहले अद्यतन

किसी भी भविष्य के लिए ... यहां सटीक दृष्टिकोण है जिसे मैंने लेना शुरू कर दिया है। यह इतनी अच्छी तरह से काम कर रहा है कि हम इसे प्रत्येक डेटाबेस में हर मेज पर कर रहे हैं। मुझे सही दिशा में इंगित करने के लिए नीचे दिए गए उत्तर के लिए धन्यवाद।

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
यह एक विकल्प है, यह वही है जो ईटीएल प्रक्रिया के लिए इस्तेमाल किया जा रहा है, लेकिन ऊपर की मूंछें इस पर एक दूसरी राय चाहती हैं कि यह काम किया है या नहीं, इसलिए एसएसआईएस का उपयोग करके यह साबित करने के लिए कि एसएसआईएस ने इसे सही माना है, जैसे फैंसी शब्द को छोड़ देना पसंद नहीं है एमडी 5 हैश।
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 सर्वर 2005 चलाने वाले एक ही सर्वर से जुड़े दो अलग-अलग डेटाबेस में 21 प्रकार के नियमित क्षेत्रों के साथ दो तालिकाओं की तुलना करता है। तालिका में लगभग 3 मिलियन पंक्तियाँ हैं, और लगभग 25000 पंक्तियाँ भिन्न हैं। टेबल पर प्राथमिक कुंजी अजीब है, हालांकि, क्योंकि यह 10 फ़ील्ड की एक संयुक्त कुंजी है (यह एक ऑडिट टेबल है)।

प्रश्नों के निष्पादन की योजना के लिए कुल लागत 184.25879 UNIONऔर 184.22983 है UNION ALL। पेड़ की लागत केवल पंक्तियों को वापस करने से पहले अंतिम चरण में भिन्न होती है, संघनन।

वास्तव में किसी भी क्वेरी को निष्पादित करने में लगभग 42s प्लस 3s के बारे में वास्तव में पंक्तियों को प्रसारित करना होता है। दो प्रश्नों के बीच का समय समान है।

दूसरा जोड़:

यह वास्तव में बहुत तेज़ है, प्रत्येक एक लगभग 2.5 मिलियन में 3 मिलियन पंक्तियों के खिलाफ चल रहा है:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB

यदि उन लोगों के परिणाम मेल नहीं खाते हैं, तो आप जानते हैं कि टेबल अलग हैं। हालांकि, अगर परिणाम कर मैच, तो आप कर रहे हैं नहीं गारंटी है कि टेबल [अत्यधिक संभावना नहीं] चेकसम टकराव की संभावना को की वजह से समान हैं।

मुझे यकीन नहीं है कि तालिकाओं के बीच डेटाटाइप परिवर्तन इस गणना को कैसे प्रभावित करेगा। मैं क्वेरीज़ को systemविचारों या information_schemaविचारों के विरुद्ध चलाऊंगा।

मैंने 5 मिलियन पंक्तियों के साथ किसी अन्य तालिका के खिलाफ क्वेरी की कोशिश की और वह लगभग 5s में भाग गई, इसलिए यह बड़े पैमाने पर O (n) प्रतीत होता है।


8

यहाँ कई विचार दिए गए हैं जो मदद कर सकते हैं:

  1. भिन्न डेटा भिन्न टूल आज़माएं - क्या आपने Idera के SQL तुलना टूलसेट या ApexSQL डेटा डिफ की कोशिश की है । मुझे एहसास है कि आप पहले से ही आरजी के लिए भुगतान करते हैं, लेकिन आप अभी भी काम पाने के लिए परीक्षण मोड में इनका उपयोग कर सकते हैं;)।

  2. विभाजित करें और जीतें - 10 छोटे तालिकाओं में विभाजन तालिका के बारे में कैसे कुछ व्यावसायिक डेटा तुलना टूल द्वारा हैंडल किया जा सकता है?

  3. अपने आप को केवल कुछ स्तंभों तक सीमित करें - क्या आपको वास्तव में सभी स्तंभों में डेटा की तुलना करने की आवश्यकता है?


7

मेरा मानना ​​है कि आपको BINARY_CHECKSUM की जांच करनी चाहिए, हालांकि मैं रेड गेट टूल का विकल्प चुनूंगा:

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

कुछ इस तरह:

SELECT BINARY_CHECKSUM(*) from myTable;

क्या यह तालिकाओं के स्कीमा (विभिन्न स्तंभ नाम या डेटाटाइप्स) में अंतर का पता लगाएगा?
ypercube y

@ ypercube y हाँ, मैं इसकी पुष्टि कर सकता हूँ। मैं CHECKSUM_AGG(BINARY_CHECKSUM(*))दो समान तालिकाओं के बीच के परीक्षण का परीक्षण कर रहा था जहाँ चेकसम का मिलान हुआ था। जब मैंने किसी एक तालिका में एक कॉलम जोड़ा, उसके बाद चेकसम मान समान नहीं थे।
जेफ मर्गलर

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

इसे एक चौखटे में देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.