3

我有一个应用程序,用于将大型数据集(数百万条记录)从一个数据库导入另一个数据库,在此过程中进行比较(IE 删除已删除的内容、更新内容等)。由于许多外键约束等,为了加快应用程序的处理速度,它将整个目标数据库加载到内存中,然后尝试加载源数据库的部分内容并进行内存比较,更新记忆中的目的地。最后,它将这些更改写回目的地。数据库不是一对一匹配的,所以一个表中的一个表可能是另一个表中的多个表,等等。

所以我的问题是:目前运行这个过程需要几个小时(有时接近一天,具体取决于添加/更改的数据量),这使得调试变得非常困难。从历史上看,当我们遇到错误时,我们会进行更改,然后重新运行应用程序,该应用程序必须再次将所有数据加载到内存中(需要相当长的时间),然后运行导入过程,直到我们到达我们所在的部分然后我们交叉手指,希望我们的改变奏效。这不好玩:(

为了加快调试过程,我通过将导入代码移动到单独的 dll 中来进行架构更改,该 dll 加载到单独的 appdomain 中,以便我们可以卸载它、进行更改并重新加载它并尝试运行导入的一部分再次,从我们离开的地方开始,看看我们是否能得到更好的结果。当我想出这个计划时,我以为我是个天才 :) 但它有一个问题。我要么必须将目标数据库中的所有数据加载到第二个 appdomain 中,然后在卸载之前,使用 [Serializable] 交易将其全部复制到第一个(卸载和重新加载 dll 时这真的很慢)或加载主机 appdomain 中的数据,并在第二次使用 MarshalByRefObject 引用它(这似乎使整个过程变慢)

所以我的问题是:我怎样才能快速做到这一点?就像,最多一分钟!我很想只复制数据,就好像它只是通过引用传递一样,而不必实际进行完整复制。

我想知道是否有更好的方法来实现这一点,以便数据可以更好地在两者之间共享,或者至少在它们之间快速传递。我已经搜索并发现推荐使用数据库的东西(我们正在将数据加载到内存中以避免数据库)或者只是说使用 MarshalByRefObject 的东西。我想做一些那么简单的事情,但它还没有真正奏效。

我在某处读到加载 C++ dll 或非托管 dll 会导致它忽略应用程序域并可能引入一些问题。无论如何我可以利用它来发挥我的优势,IE,加载一个为我或其他东西保存我的列表的非托管 dll,并用它来欺骗我的应用程序为两个 appdomains 使用相同的内存,以便列表在我通过卸载应用程序域来卸载其他 dll?

我希望这是有道理的。这是我在这里的第一个问题,所以如果我做得很糟糕,请帮助我。这让我沮丧了几天。

4

2 回答 2

3

应用程序域方法是一种很好的分离方式,以便仅加载/卸载应用程序的一部分。不幸的是,正如您所发现的,在两个应用程序域之间交换数据并不容易/快速。这就像两个不同的系统进程试图进行通信,它总是比同一个进程通信慢。所以要走的路是使用最快的进程间通信机制。跳过 WCF,因为它会在此处显示您不需要的开销。使用命名管道,您可以通过它非常快速地传输数据。我以前用过,效果很好。为了更快,您可以尝试MemoryMappedFile链接),但这更难实现。从命名管道开始,如果太慢,请使用内存映射文件。

即使使用快速发送方式,您也可能遇到另一个瓶颈——数据序列化。对于大量数据,标准序列化(甚至是二进制)非常慢。您可能想查看 Google 的协议缓冲区

关于 AppDomain 的一个警告 - 应用程序域之一中的任何未捕获的异常都会导致整个过程停止。不幸的是,他们并没有那么分开。

在旁注上。我不知道您的应用程序做了什么,但数百万条记录似乎并不过分。也许还有优化的空间?

于 2012-05-25T22:20:11.430 回答
-1

您没有说它是否是 SQL Server,但是您是否考虑过使用SSIS来执行此操作?显然有一些技术可以快速处理大数据。

于 2012-05-25T22:34:57.837 回答