2009-05-18 119 views
1

我有一個要求,我必須從數據庫中選擇大約6000萬條記錄。一旦我有了ResultSet中的所有記錄,那麼我必須根據客戶需求(日期格式和數字格式)合成一些列,然後我必須將所有記錄寫入文件(輔助內存)中。場景的最佳設計

  • 目前,我正在從數據庫中選擇一天的記錄(7天選擇7天)並將它們放入HashMap。從HashMap中讀取併合成一些列,最後寫入文件(單獨文件7天)。
  • 最後,我將所有7個文件合併到一個文件中。

  • 但是這整個過程需要6個小時才能完成。爲了改善這一過程,我創建了7天7天的線程,所有線程都編寫了單獨的文件。

  • 最後,我將所有7個文件合併到一個文件中。這個過程需要2個小時。但是我的程序在1小時後會進入OutOfMemory。

請建議最好的設計,這種情況下,我應該使用一些緩存機制,如果是的話,哪一個又如何呢?

注意:客戶端不希望在數據庫中更改任何內容,如創建索引或存儲過程,他們不想觸摸數據庫。 在此先感謝。

+0

你能告訴我們你正在使用的RDMS嗎?這將影響可能可用的面向數據庫的解決方案。 另外,您可以告訴我們數據庫是專爲事務處理(高度規範化)還是更多分析處理(高度非規範化)設計的? – 2009-05-18 16:37:11

+0

客戶端不想在數據庫中更改任何內容。他們還沒有準備好創建新的索引或SP或對錶格進行規範化。 – 2009-05-18 16:48:47

回答

4

您是否需要將所有記錄存儲在內存中才能格式化它們?您可以嘗試通過流程和文件的權限對記錄進行流式處理。如果你甚至能夠進一步分解查詢,你可能能夠開始處理結果,而你仍然可以檢索它們。

根據你的數據庫後端,他們可能有工具來幫助解決這個問題,比如SSIS for Sql Server 2005+。

編輯

我是一個.NET開發人員,所以讓我提出什麼,我會在.NET做,希望你可以轉換成在Java端媲美的技術。

ADO.Net有一個DataReader,它是一個結果集的只讀,只讀(Firehose)遊標。它在查詢執行時返回數據。這個非常重要。從本質上講,我的邏輯是:

IDataReader reader=GetTheDataReader(dayOfWeek); 

while (reader.Read()) 
{ 
    file.Write(formatRow(reader)); 
} 

由於這一點的同時,我們正在返回你不打算上我猜測的網絡接入塊行正在執行對你是一個巨大的瓶頸。這裏的關鍵是我們沒有將這些內容長時間存儲在內存中,因爲我們循環讀取器會放棄結果,並且文件會將行寫入磁盤。

0

取決於您使用的數據庫,但如果是SQL Server,我會推薦使用類似SSIS的方法來執行此操作,而不是編寫程序。

+0

客戶端尚未準備好更改數據庫中的任何內容。沒有索引和存儲過程。 – 2009-05-18 16:46:57

2

我想喬什的建議是這樣的:

你有循環,在那裏你目前通過你查詢的所有結果記錄(只是用僞這裏代碼):

while (rec = getNextRec()) 
    { 
    put in hash ... 
    } 

for each rec in (hash) 
    { 
    format and save back in hash ... 
    } 

for each rec in (hash) 
    { 
    write to a file ... 
    } 

instead, do it like this: 

while (rec = getNextRec()) 
    { 
    format fields ... 
    write to the file ... 
    } 

那麼你在內存中一次不會有超過1條記錄......並且您可以處理無限數量的記錄。

1

顯然一次讀取6000萬條記錄會耗盡你所有的記憶 - 所以你不能這樣做。 (即你的7線程模型)。每次讀取6000萬條記錄會耗盡您所有的時間 - 所以您無法做到這一點(即您最初的讀取文件模型)。

所以....你將不得不妥協,並做一些兩者。

Josh說得對 - 打開一個光標到你的數據庫,它只是簡單地讀取下一個記錄,一個接一個地以最簡單,功能最強的方式。一個「firehose」遊標(或者稱爲只讀遊標,只向前遊標)就是你想要的,因爲它在數據庫上施加的負載最小。數據庫不會讓您更新記錄,也不會讓您在記錄集中向後退出,而您不希望這樣做,因此它不需要處理記錄的內存。

現在你有了這個光標,DB每次給你一條記錄 - 讀取它,並將它寫入一個文件(或幾個文件),這應該會很快完成。然後你的任務是將文件合併到1,並且順序正確,這相對容易。

鑑於您必須處理的記錄數量,我認爲這是您的最佳解決方案。

但是......無論如何,看到你做得相當不錯,爲什麼不減少線程的數量,直到你處於你的內存限制之內。批量處理在一夜之間運行的很多公司,這似乎是另一個過程。