RTh*_*mas 15 sql-server etl sql-server-2008-r2 except
我们正在做一个 ETL 过程。当一切都说完后,有一堆表格应该是相同的。验证这些表(在两个不同的服务器上)实际上相同的最快方法是什么?我说的是架构和数据。
我可以在表上做一个散列,就像我可以在单个文件或文件组上一样 - 将一个与另一个进行比较。我们有 Red-Gate 数据比较,但由于有问题的表每个都包含数百万行,我想要一些性能更高的东西。
一种让我感兴趣的方法是对 union 语句的这种创造性使用。但是,如果可能的话,我想进一步探索散列的想法。
发布答案更新
对于任何未来的访客......这是我最终采取的确切方法。它工作得很好,我们在每个数据库的每个表上都这样做。感谢下面的答案为我指明了正确的方向。
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
Run Code Online (Sandbox Code Playgroud)
Bac*_*its 19
这是我之前所做的:
(SELECT 'TableA', * FROM TableA
EXCEPT
SELECT 'TableA', * FROM TableB)
UNION ALL
(SELECT 'TableB', * FROM TableB
EXCEPT
SELECT 'TableB', * FROM TableA)
Run Code Online (Sandbox Code Playgroud)
它在大约 1,000,000 行的表上工作得很好,但我不确定它在超大表上的工作情况如何。
添加:
我已经对我的系统运行了查询,该系统将两个表与两个不同的数据库中的常规类型的 21 个字段进行了比较,这些数据库连接到运行 SQL Server 2005 的同一台服务器上。该表大约有 300 万行,其中大约有 25000 行不同。然而,表上的主键很奇怪,因为它是 10 个字段的组合键(它是一个审计表)。
查询的执行计划的总成本为 184.25879 forUNION
和 184.22983 for UNION ALL
。树的成本仅在返回行之前的最后一步(连接)有所不同。
实际执行任一查询需要大约 42 秒加上大约 3 秒才能实际传输行。两次查询之间的时间相同。
第二个补充:
这实际上非常快,每一个在大约 2.5 秒内运行 300 万行:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableA
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM TableB
Run Code Online (Sandbox Code Playgroud)
如果这些结果不匹配,您就知道表格不同。但是,如果结果做比赛,你不能保证该表是因为校验和冲突的[不大可能]的机会是相同的。
我不确定表之间的数据类型更改会如何影响此计算。我会针对system
视图或information_schema
视图运行查询。
我尝试对另一个有 500 万行的表进行查询,该表运行了大约 5 秒,所以它似乎主要是 O(n)。
小智 7
我相信您应该调查 BINARY_CHECKSUM,尽管我会选择 Red Gate 工具:
http://msdn.microsoft.com/en-us/library/ms173784.aspx
像这样的东西:
SELECT BINARY_CHECKSUM(*) from myTable;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
25156 次 |
最近记录: |