是否有一种设计模式可以帮助比较大量数据?

时间:2012-06-20 15:05:50

标签: c# sql-server tsql design-patterns ado.net

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

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

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

我担心的是我将处理的数据大小约为200 MB。

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

你会推荐什么?是否已经存在比较海量数据的模式?

6 个答案:

答案 0 :(得分:2)

200 MB应该不是问题。 .NET应用程序可以同时处理更多内容。

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

答案 1 :(得分:1)

您可以使用两个SqlDataReaders。它们一次只在内存中有一行,只有前向,而且效率极高。从阅读器中取回行后,您可以比较这些值。这是一个例子。

请参阅MSDN

答案 2 :(得分:1)

最具扩展性的解决方案是创建SQLCLR函数以执行所需的比较。

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

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

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

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

答案 3 :(得分:1)

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

1)二进制搜索。 - 您可以在表2中找到匹配的行而不使用二进制搜索扫描所有表2,这将显着减少比较次数

2)如果要查找两个表之间的重叠/匹配/缺失行,可以按相同顺序对两个表进行排序。然后你可以同时遍历这两个表,保持指向每个表的当前行的指针。如果表1在表2的“前面”,则只增加表2指针,直到它们相等,或者表2在前面。然后,一旦表2前进,您开始递增表1直到它前面。通过这种方式,您只需要遍历每个表中的每个记录一次,并确保没有您错过的匹配。

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

如果您只需要在某个行或彼此的某个范围内执行某些操作,此解决方案也会有效。

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

答案 4 :(得分:0)

您可以使用快速ETL / SSIS作业将数据转移到同一数据库吗?这将允许您执行可能更容易处理的集合操作。如果没有,我会同意有关只有一个表的内存数据阅读器的建议

答案 5 :(得分:0)

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

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

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

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