2012-05-25 95 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可以使大數據快速。

相關問題