2013-06-25 28 views
3

我從web服務讀取大CSV像這樣:BufferedReader排隊的數據在哪裏?

br = new BufferedReader(new InputStreamReader(website.openStream(), "UTF-16"));

我逐行讀取和寫入到數據庫中。寫入數據庫是這個操作的瓶頸,我想知道是否有可能「超時」web服務,所以我得到的情況下,web服務只是切斷連接,因爲我沒有從它讀取任何東西。

或者BufferedReader是否只是將流緩衝到內存中,直到我讀取它?

+0

你期待db有多慢?即從插座讀取什麼樣的延遲? – jtahlborn

回答

1

是的,當您寫入數據庫時​​,web服務流可能會超時。如果數據庫的速度非常慢,可能會超時,那麼在將數據推入數據庫之前,您可能需要在本地複製文件。

+0

是的,一種選擇是將其下載到本地機器,然後從那裏讀取;另一種方法是實際緩衝數行數據並將它們作爲一批寫入;想到的第三個選項是有兩個線程 - 一個用於讀取和緩存多行數據,另一個用於寫入數據庫。 – carlspring

+0

@carlspring - 顯然使數據庫更快是一個解決方案。除非你願意將整個文件放在內存中(這是一個糟糕的設計),否則擁有多個線程無濟於事。 – jtahlborn

+0

不......在內存中讀取整個文件是一個壞主意。但是...緩衝幾行CSV應該是合理的。 – carlspring

0

BufferedReader將如您所猜測的那樣將流的內容讀入內存。假設數據已經存在於緩衝區中,任何對readreadLine的調用都將從緩衝區讀取數據,而不是從原始數據流讀取數據。這裏的優點是數據以較大批量讀取,而不是在每次調用readreadLine時從流中請求。

如果您正在閱讀大量數據,您可能只會遇到像您所描述的超時。我找到一個可信的參考時遇到了一些麻煩,但我看到BufferedReader上的默認緩衝區大小是8192字節(8kb)。這意味着如果您的數據流正在讀取多於8kb的數據,緩衝區可能會填充並導致您的進程在從數據流中讀取更多數據之前等待數據庫瓶頸。

如果您認爲您需要保留比此更大的緩衝區,那麼BufferedReader構造函數會被重載,第二個參數允許您以字節爲單位指定緩衝區的大小。但請記住,除非您移動足夠小的數據以緩衝整個流,否則即使使用更大的緩衝區也可能遇到同樣的問題。

br = new BufferedReader(new InputStreamReader(website.openStream(), "UTF-16"), size); 

將初始化BufferedReadersize字節的緩衝區。

編輯:

閱讀@基思的評論之後,我認爲他得到了它在這裏。如果您遇到超時,較小的緩衝區會導致您更頻繁地從套接字讀取數據,希望能夠消除該問題。如果他發表了一個答案,你應該接受他的答案。

+0

創建更大的緩衝區如何解決問題? – jtahlborn

+0

這只是一個有效的修復,如果他可以緩衝來自流的整個數據。我會更新答案以反映這一點。 – Brian

+1

我其實不會期望任何問題,除非你的數據庫真的很慢(需要超過30秒才能插入8kB CSV中包含的行)。但是,如果是這種情況,請調整緩衝區大小DOWN,以便在插入數據庫時​​更頻繁地讀取套接字。 – Keith

0

+1對於Brian的回答。

此外,我建議你看看我的csv-db-tools on GitHubcsv-db-importer模塊說明如何將大型CSV文件導入數據庫。該代碼經過優化,可以一次插入一行,並使內存免受大型CSV文件緩衝的數據的影響。

+0

這個問題不是內存管理(雖然這也可能是一個問題),但套接字超時。 – jtahlborn

+0

那麼,在這種情況下,將套接字的超時設置爲合理的值並從其流中讀取,然後寫入數據庫。 – carlspring

+0

你不能總是控制套接字超時。例如,在客戶端和服務器之間可能存在固定的空閒超時的防火牆。 – jtahlborn

0

BufferedReader只是將塊讀入一個內部緩衝區,其默認大小未指定,但已經有4096個字符多年。當你不叫它時,它什麼也不做。

但我不認爲你的感知問題甚至存在。我看不出Web服務怎麼知道。在TCP中寫超時很難實現。有些平臺具有API,但它們不受Java支持。

最有可能的是,Web服務只是使用阻塞模式套接字,如果讀取速度不夠快,它只會在寫入時阻塞。