Мы делаем процесс ETL. Когда все сказано и сделано, есть несколько таблиц, которые должны быть идентичными. Какой самый быстрый способ проверить, что эти таблицы (на двух разных серверах) на самом деле идентичны. Я говорю о схеме и данных.
Могу ли я сделать хеш для таблицы сам по себе, как если бы я мог в отдельном файле или файловой группе - сравнить один с другим. Мы сравниваем данные Red-Gate, но так как таблицы содержат миллионы строк в каждой, я бы хотел что-то более производительное.
Один подход, который меня заинтриговал - это творческое использование заявления профсоюза . Но я хотел бы изучить идею хэша немного дальше, если это возможно.
ПОСЛЕ ОТВЕТА ОБНОВЛЕНИЕ
Для любых будущих визитеров ... вот точный подход, который я в итоге выбрал. Это сработало так хорошо, что мы делаем это на каждой таблице в каждой базе данных. Спасибо за ответы ниже, чтобы указать мне в правильном направлении.
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
источник
Ответы:
Вот что я сделал раньше:
Он работал достаточно хорошо для таблиц, которые содержат около 1 000 000 строк, но я не уверен, насколько хорошо это будет работать с очень большими таблицами.
Добавлено:
Я запустил запрос к моей системе, который сравнивает две таблицы с 21 полем регулярных типов в двух разных базах данных, подключенных к одному и тому же серверу, на котором выполняется SQL Server 2005. Таблица содержит около 3 миллионов строк, и примерно 25000 строк различны. Однако первичный ключ в таблице странный, так как это составной ключ из 10 полей (это таблица аудита).
Планы выполнения запросов имеют общую стоимость 184,25879 для
UNION
и 184,22983 дляUNION ALL
. Стоимость дерева отличается только на последнем шаге перед возвратом строк, конкатенации.На самом деле выполнение любого запроса занимает около 42 с плюс около 3 с для фактической передачи строк. Время между двумя запросами идентично.
Второе дополнение:
На самом деле это очень быстро, каждый из которых работает с 3 миллионами строк примерно за 2,5 секунды:
Если результаты не совпадают, вы знаете, что таблицы разные. Однако, если результаты действительно совпадают, вы не гарантируете, что таблицы идентичны из-за [крайне маловероятной] вероятности коллизий контрольной суммы.
Я не уверен, как изменения типа данных между таблицами повлияют на этот расчет. Я бы запустил запрос против
system
представлений илиinformation_schema
представлений.Я пытался выполнить запрос к другой таблице с 5 миллионами строк, и эта строка выполнялась примерно за 5 секунд, поэтому, по-видимому, это в основном O (n).
источник
Вот несколько идей, которые могут помочь:
Попробуйте другой инструмент для различий в данных - пробовали ли вы набор инструментов Idera для сравнения SQL или ApexSQL Data Diff . Я понимаю, что вы уже заплатили за RG, но вы все равно можете использовать их в пробном режиме, чтобы выполнить работу;).
Разделяй и властвуй - как насчет разделения таблиц на 10 небольших таблиц, которые могут быть обработаны каким-либо коммерческим инструментом сравнения данных?
Ограничьте себя только некоторыми столбцами - вам действительно нужно сравнивать данные во всех столбцах?
источник
Я считаю, что вы должны изучить BINARY_CHECKSUM, хотя я бы выбрал инструмент Red Gate:
http://msdn.microsoft.com/en-us/library/ms173784.aspx
Что-то вроде этого:
источник
Если у вас есть первичный ключ, иногда это лучший способ проверить различия, потому что строки, которые должны быть одинаковыми, отображаются вместе.
Смотрите это в sqlfiddle .
источник