2012-05-25 144 views
3

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

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

为了加快调试过程,我正在通过将导入代码移动到一个单独的dll中,将其加载到单独的appdomain中,以便我们可以卸载它,进行更改并重新加载它,然后尝试再次运行一部分导入操作,选择我们离开的位置,然后看看我们是否得到了更好的结果。当我提出这个计划时,我认为我是一个天才:)但它有一个问题。我必须将所有数据从目标数据库加载到第二个appdomain中,然后在卸载之前,使用[Serializable]处理(卸载和重新加载dll时的速度真的很慢)或加载时将所有数据全部复制到第一个主机应用程序域中的数据,并在第二次使用MarshalByRefObject引用它(原来看起来使整个过程变慢)

所以我的问题是:我该如何快速做到这一点?就像,最多一分钟!我很想复制数据,就好像它只是通过引用传递,而不必真正做完整的副本。

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

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

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

+0

有趣的问题。但是,这不是代码在某种测试覆盖下(即使在高水平)?为了基督的缘故,您不应该在调试时等待*那么久。尽管我会尽可能地加快速度,但请注意,一旦出现问题,您必须尽快浪费您宝贵的时间。我很好奇真正的答案是什么,虽然:) –

回答

3

应用程序域方法是为了仅加载/卸载部分应用程序而分离的好方法。不幸的是,正如您发现的那样,在两个应用程序域之间交换数据并不容易/快速。它就像两个不同的系统进程试图进行通信一样,它总是比相同的进程通信慢。所以要走的路是尽可能快的进程间通信机制。跳过WCF,因为它在这里不需要广告开销。使用named pipes,通过它您可以非常快速地传输数据。我以前用过它,效果很好。要走得更快,您可以尝试MemoryMappedFilelink),但实施起来更加困难。从命名管道开始,如果速度太慢,请转到内存映射文件。

即使使用快速发送方式,您可能会遇到另一个瓶颈 - 数据序列化。对于大量数据,标准序列化(甚至二进制)非常缓慢。你可能想看看谷歌的protocol buffers

AppDomain上的一个警告词 - 在任何一个应用程序域中的任何未捕获的异常都会导致整个过程失败。不幸的是,他们并没有分开。

在侧面说明。我不知道你的应用程序做了什么,但数百万条记录似乎并不过分。也许有优化的空间?

-1

你没有说它是否是SQL Server,但你看过使用SSIS这样做吗?显然有some techniques可以使大数据快速。

相关问题