2015-01-14 44 views
0

我有一個文件(讓我們稱之爲enrolled_students.txt),我需要在Perl中讀取。該文件每行都有數據,因此需要引用其他文件以獲取更多信息。Perl:並行讀取和處理多個文件

例如,主數據庫將具有名稱和地址。但根據每個人的國籍,我必須參考其他文件(按國家排序)來查找匹配的姓名,國籍和家庭地址。

假設我有100個name_of_country.txt文件,並且在我的enrolled_students.txt中有10,000行。我的問題是:

  • 我是否閱讀enrolled_students.txt中的每一行,並解析其他100個文件以查找匹配項?這似乎是一個可怕的方式來處理這些數據。有沒有更快的方法來做到這一點?
  • 我可以在並行模式(多線程)下執行此進程嗎?

感謝, 漢斯

+2

*「這似乎是一個可怕的方式來處理這些數據。」*是的。 *「有沒有更快的方法來做到這一點?」*使用數據庫而不是平面文本文件。 – ThisSuitIsBlackNot

+0

原始數據僅作爲txt文件提供,要求僅使用perl。 – Hans

+1

看看['DBD :: SQLite'](https://metacpan.org/pod/DBD::SQLite)。它是獨立的(您不必安裝單獨的數據庫服務器),並且可能比您自己拼湊的任何內容都快得多。當然,你必須首先將初始數據集加載到數據庫中......這些文本文件經常變化嗎? – ThisSuitIsBlackNot

回答

1

你在這裏試圖做什麼類似於數據庫引擎在將兩個表中的數據連接在一起時必須執行的操作。一個數據庫引擎通常會有多個不同的連接計劃可供選擇,並且它會嘗試根據它對每個表中的數據的瞭解來選擇最佳計劃。

這同樣適用於你。有幾種方式加入到數據的最佳方式將取決於多種因素,如每個輸入文件的大小,無論是預先排序等

一些可能的方案:

  1. 一個'嵌套循環',您可以在其中讀取enrolled_students.txt文件的每一行,併爲每一行遍歷其他文件以查找匹配。不太可能很快,如果文件太大而無法使其他解決方案變得實用,則可能只會選擇此選項。

  2. 'Hash Join',你可以在其中讀取要連接的數據的一半(在你的例子中,可能是name_of_country.txt)到一個由散列索引的數據結構中。然後,對於其他文件的每一行,您可以在散列中查找相應的行。只要有足夠的內存一次存儲兩組數據中的至少一組數據,這可以是相當高的性能。

  3. 如果這兩個文件都按某種排序順序排序,按照相同的鍵排序,則可以使用「合併連接」。這就是您一次讀取兩個文件的行,將記錄與拉鍊中的牙齒相匹配的地方。

上面假設一個簡單的情況,需要連接兩個數據文件。您的問題涉及100個不同的name_of_country.txt文件,這可能會使問題複雜化。

關於你的第二個問題 - 你可以使用並行處理 - 這可能只有在處理是CPU限制時纔有用。除非您發現它實際上是CPU綁定的,否則生成分叉或線程解決方案的複雜性可能不合理。

最後 - 如果您要對同一數據進行多次分析運行,建議將數據導入真實數據庫並使用該運行查詢。這會爲你節省很多編碼工作。

+0

感謝您提供有見地的信息 – Hans

0

我將把你的問題:如何有效地執行兩個文件一個「加入」的操作和這裏就是答案。

其實在Unix中有一個join命令。 http://linux.die.net/man/1/join

假設你有兩個文件,學生和student_with_country:

student: [name] [age] [...] 
student_with_country: [name] [country] [...] 

你可以這樣做:

join student student_with_country (by default, it will join based on the first field) 

接下來的問題是如何使它更快地通過使用多個內核?

答案是parallel命令。基本上,你可以使用它來運行一個簡單的map-reduce程序。例如,在這種情況下,

cat student_with_country | parallel --block 10M --pipe join student - 

它會將student_with_country文件分成10M個塊,並行運行join命令。這樣就可以利用多個內核的功耗。

+0

感謝您的建議。如果只有兩個文件並且它們具有相同的行數,這可能效果最好。問題是文件student_with_country與學生文件有不同的格式,並且還有額外的垃圾,我不需要。 – Hans

+1

'join'假定排序文件。 – reinierpost