Wir machen einen ETL-Prozess. Letztendlich gibt es eine Reihe von Tabellen, die identisch sein sollten. Wie lässt sich am schnellsten überprüfen, ob diese Tabellen (auf zwei verschiedenen Servern) tatsächlich identisch sind? Ich spreche sowohl Schema als auch Daten.
Kann ich einen Hash auf dem Tisch ausführen, als wäre ich in der Lage, eine einzelne Datei oder Dateigruppe mit einer anderen zu vergleichen? Wir haben Red-Gate-Daten verglichen, aber da die fraglichen Tabellen jeweils Millionen von Zeilen enthalten, hätte ich gerne etwas Performanteres.
Ein Ansatz, der mich fasziniert, ist die kreative Verwendung der Gewerkschaftserklärung . Aber ich möchte die Hash-Idee, wenn möglich, ein wenig weiter untersuchen.
POST ANTWORT UPDATE
Für alle zukünftigen Besucher ... hier ist der genaue Ansatz, den ich letztendlich gewählt habe. Es hat so gut funktioniert, dass wir es für jede Tabelle in jeder Datenbank tun. Vielen Dank an die Antworten unten, die mich in die richtige Richtung gelenkt haben.
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
quelle
Antworten:
Folgendes habe ich bereits getan:
Bei Tabellen mit etwa 1.000.000 Zeilen funktioniert es gut genug, aber ich bin mir nicht sicher, wie gut das bei extrem großen Tabellen funktionieren würde.
Hinzugefügt:
Ich habe die Abfrage auf meinem System ausgeführt, das zwei Tabellen mit 21 regulären Feldern in zwei verschiedenen Datenbanken vergleicht, die an denselben Server mit SQL Server 2005 angeschlossen sind. Die Tabelle enthält ungefähr 3 Millionen Zeilen und es gibt ungefähr 25000 verschiedene Zeilen. Der Primärschlüssel auf der Tabelle ist jedoch seltsam, da er aus 10 Feldern zusammengesetzt ist (es ist eine Prüftabelle).
Die Ausführungspläne für die Abfragen haben Gesamtkosten von 184.25879 für
UNION
und 184.22983 fürUNION ALL
. Die Baumkosten unterscheiden sich nur im letzten Schritt vor der Rückgabe von Zeilen, der Verkettung.Das Ausführen einer der beiden Abfragen dauert ungefähr 42 Sekunden plus ungefähr 3 Sekunden, um die Zeilen tatsächlich zu übertragen. Die Zeit zwischen den beiden Abfragen ist identisch.
Zweiter Zusatz:
Das ist eigentlich extrem schnell, jeder läuft gegen 3 Millionen Zeilen in ungefähr 2,5 Sekunden:
Wenn die Ergebnisse nicht übereinstimmen, wissen Sie, dass die Tabellen unterschiedlich sind. Stimmen die Ergebnisse jedoch überein, kann aufgrund der [höchst unwahrscheinlichen] Wahrscheinlichkeit von Prüfsummenkollisionen nicht garantiert werden, dass die Tabellen identisch sind.
Ich bin nicht sicher, wie sich Datentypänderungen zwischen Tabellen auf diese Berechnung auswirken würden. Ich würde die Abfrage gegen die
system
Ansichten oderinformation_schema
Ansichten ausführen .Ich habe versucht, die Abfrage für eine andere Tabelle mit 5 Millionen Zeilen durchzuführen, und diese wurde in etwa 5 Sekunden ausgeführt. Es scheint sich also weitgehend um O (n) zu handeln.
quelle
EXCEPT
Anweisungen aufweist. Ich bin jetzt wirklich gespannt, ob es so ist. Es ist jedoch logischer, für das RDBMS explizit zu sein, daher aktualisiere ich es.Hier sind einige Ideen, die helfen könnten:
Probieren Sie verschiedene Daten Diff - Tool - haben Sie versucht Idera SQL Vergleich Toolset oder ApexSQL Daten Diff . Mir ist klar, dass Sie bereits für RG bezahlt haben, aber Sie können diese weiterhin im Testmodus verwenden, um die Arbeit zu erledigen;).
Teilen und erobern - wie wäre es, wenn Sie Tabellen in 10 kleinere Tabellen aufteilen, die von einem kommerziellen Datenvergleichstool verarbeitet werden können?
Beschränken Sie sich auf einige Spalten. Müssen Sie wirklich Daten in allen Spalten vergleichen?
quelle
Ich glaube, Sie sollten BINARY_CHECKSUM untersuchen, obwohl ich mich für das Red Gate-Tool entscheiden würde:
http://msdn.microsoft.com/en-us/library/ms173784.aspx
Etwas wie das:
quelle
Wenn Sie einen Primärschlüssel haben, ist dies manchmal eine bessere Möglichkeit, Unterschiede zu untersuchen, da die Zeilen, die gleich sein sollten, zusammen angezeigt werden.
Sehen Sie es in einer SQL-Geige .
quelle