我有一个应用程序用于将一个大型数据集(数百万条记录)从一个数据库导入另一个数据库,在该过程中执行差异(IE删除已删除的内容,更新内容等)。由于许多外键约束等,并试图加快应用程序的处理,它将整个目标数据库加载到内存中,然后尝试加载部分源数据库并进行内存中比较,更新目的地在记忆中。最后,它将这些更改写回目标。数据库一对一不匹配,因此一个表中的单个表可能是另一个表中的多个表,等等。
所以我的问题是:它目前需要几个小时来运行这个过程(有时接近一天,具体取决于添加/更改的数据量),这使得调试非常困难。从历史上看,当我们遇到错误时,我们进行了更改,然后重新运行必须再次将所有数据加载到内存中的应用程序(需要相当长的时间),然后运行导入过程直到我们到达我们的部分然后我们交叉手指,希望我们的改变有效。这不好玩:(
为了加快调试过程,我通过将导入代码移动到一个单独的dll中进行体系结构更改,该dll被加载到一个单独的appdomain中,以便我们可以卸载它,进行更改并重新加载它并尝试运行一个部分再次进口,从我们离开的地方开始,看看我们是否会获得更好的结果。当我想出这个计划时,我以为我是个天才:)但它有一个问题。我要么必须将目标数据库中的所有数据加载到第二个appdomain中,然后在卸载之前使用[Serializable]交易将其全部复制到第一个(这在卸载和重新加载dll时非常慢)或加载主机appdomain中的数据,并在第二个使用MarshalByRefObject引用它(结果似乎使整个过程看起来很慢)
所以我的问题是:我怎样才能快速完成这项工作?比如,最多一分钟!我希望只是复制数据,好像它只是通过引用传递而不必实际完整复制。
我想知道是否有更好的方法来实现这一点,以便更好地在两者之间共享数据,或者至少在两者之间快速传递。我已经搜索并发现了建议使用数据库的事情(我们在内存中加载数据以避免数据库)或者只是说要使用MarshalByRefObject。我喜欢做一件容易的事,但还没有真正奏效。
我在某处读到加载C ++ dll或非托管dll会导致它忽略app域并可能引入一些问题。无论如何我可以使用这个对我有利,IE,加载一个非托管的dll,它为我或者某些东西保存我的列表,并使用它来欺骗我的应用程序使用相同的内存对于两个appdomains,以便列表只是坚持我通过卸载app域来卸载其他dll?
我希望这是有道理的。这是我在这里的第一个问题,所以如果我做了一个糟糕的工作,请帮助我。这让我几天感到沮丧。
答案 0 :(得分:3)
App域方法是一种很好的分离方法,只是为了加载/卸载部分应用程序。不幸的是,正如您所发现的,在两个应用域之间交换数据并不容易/快速。它就像两个尝试通信的不同系统进程一样,总是比同一个进程通信慢。所以要走的路是使用最快的进程间通信机制。跳过WCF,因为它在这里不需要广告开销。使用named pipes可以非常快速地传输数据。我以前用过它,效果很好。为了更快,您可以尝试MemoryMappedFile
(link),但这更难实施。从命名管道开始,如果速度太慢,请选择内存映射文件。
即使使用快速发送方式,您也可能遇到另一个瓶颈 - 数据序列化。对于大量数据,标准序列化(甚至二进制)非常慢。您可能需要查看Google的protocol buffers。
AppDomain上的一个注意事项 - 其中一个应用程序域中的任何未捕获的异常都会导致整个过程失败。不幸的是,它们并没有那么分开。
旁注。我不知道你的应用程序做了什么,但数百万条记录似乎并不过分。也许还有优化空间?
答案 1 :(得分:-1)
您没有说它是否是SQL Server,但您是否考虑使用SSIS来执行此操作?显而易见some techniques可以使大数据速度加快。