2

我需要比较位于不同服务器的 2 个 SQL 表的特定内容:Table1 和 Table2。

我想将 Table1 中的每一行与 Table2 的全部内容进行比较。

比较逻辑有点复杂,所以我想应用一个用 C# 编写的逻辑运算符。所以我不想对 SQL 查询本身进行比较。

我担心的是我将处理的数据大小将在 200 MB 左右。

我正在考虑使用 ADO.Net 将数据加载到 DataTable 中并在内存上进行比较。

你会推荐什么?是否已经有类似模式的方法来比较海量数据?

4

6 回答 6

2

200 MB 应该不是问题。.NET 应用程序一次可以处理的远不止这些。

但即便如此,我可能会为表 1 使用只进数据读取器,只是因为没有充分的理由不这样做,而这应该会减少所需的内存量。您可以使用您习惯的任何结构将表 2 保存在内存中。

于 2012-06-20T15:10:45.270 回答
1

您可以使用两个 SqlDataReader。它们一次只有一行内存,只向前,而且效率极高。从读者那里取回该行后,您可以比较这些值。这是一个例子。

请参阅MSDN

于 2012-06-20T15:08:06.927 回答
1

最具可扩展性的解决方案是创建 SQLCLR 函数来执行您想要的比较。

您应该不惜一切代价避免逐行比较。往返造成的网络延迟和延迟将导致执行速度极慢。

一个快速而简单的解决方案是将数据提取到本地文件然后进行比较,因为您只需支付一次网络税。不幸的是,您失去了数据库索引和查询优化提供的加速。

一个类似的解决方案是将所有数据加载到内存中,然后使用像字典这样的索引结构来提供额外的加速。这可能是可行的,因为您的数据可以放入内存中。您仍然只需支付一次网络税,但可以从更快的执行中获益。

最具可扩展性的解决方案是创建SQLCLR代码来创建一个或多个函数来执行您想要的比较。这样您就可以完全避免网络税,避免在内存中创建和优化您自己的结构,并且可以利用索引和优化。

于 2012-06-20T15:16:13.990 回答
1

这些解决方案可能不适用,具体取决于您正在进行的比较的实际逻辑。两种解决方案都依赖于正确排序数据

1)二分查找。- 使用二分查找无需扫描所有表2即可找到表2中的匹配行,这将显着减少比较次数

2)如果您正在寻找两个表之间的重叠/匹配/缺失行,您可以按相同的顺序对两个表进行排序。然后您可以同时循环遍历两个表,并保留指向每个表的当前行的指针。如果表 1 比表 2“领先”,那么您只需递增表 2 指针,直到它们相等或表 2 领先。然后一旦表 2 领先,您就开始增加表 1 直到它领先。等等。这样,您只需遍历每个表中的每条记录一次,就可以保证没有错过任何匹配项。

如果表 1 和表 2 匹配,则匹配。当表 1 领先时,表 2 中的每一行都从表 1 中“丢失”,反之亦然。

如果您只需要在行彼此处于一定范围内或某事时采取一些行动,此解决方案也将起作用。

3) 如果您必须为表 2 中的每一行对表 1 中的每一行实际执行一些操作,那么它只是两个嵌套循环,除了进行比较/工作之外,您无能为力来优化它尽可能高效。你可以多线程它虽然取决于工作是什么以及你的瓶颈在哪里。

于 2012-06-20T15:20:20.383 回答
0

您可以使用快速 ETL/SSIS 作业将数据暂存到同一个数据库吗?这将允许您执行可能更容易处理的设置操作。如果不是,我会同意在内存中有一张表的只进数据阅读器的建议

于 2012-06-20T15:17:18.387 回答
0

几年前,我写了一个 db table 比较工具,现在是一个名为Data Comparisons的开源项目。

如果需要,您可以查看源代码。当您要比较的两个表位于同一物理服务器上时,您可以进行大量优化,因为您可以编写 SQL 查询来处理这个问题。我在数据比较中将此称为“快速比较”方法,只要您为比较的双方共享相同的连接字符串,就可以使用它。

但是,当它们位于两个不同的服务器上时,您别无选择,只能将数据拉入内存并比较那里的行。使用 SqlDataReaders 会起作用。但是,当您必须确切知道有什么不同(表 A 或表 B 中缺少哪些行,哪些行不同等)时,情况会很复杂。出于这个原因,我的方法是使用数据表,它速度较慢,但​​至少它们为您提供了必要的功能。

构建这个工具对我来说是一个学习过程。内存比较可能有优化的机会。例如,将数据加载到字典中并使用 Linq 对主键进行比较可能会更快。您甚至可以尝试 Parallel Linq 看看是否有帮助。正如 Jeffrey L Whitledge 所提到的,您不妨将 SqlDataReader 用于其中一个表,而另一个则存储在内存中。

于 2012-06-20T15:20:43.033 回答