Perl:并行读取和处理多个文件
Perl : Reading and processing multiple files in parallel
我有一个文件(暂且称之为 enrolled_students.txt)需要用 Perl 阅读。该文件每行都有数据,因此需要参考其他文件以获取更多信息。
例如,主数据库会有名称和地址。但是根据每个人的国籍,我必须参考其他文件(按国家排序)才能找到匹配的姓名、国籍和家庭住址。
假设我有 100 个 name_of_country.txt 文件,我的 enrolled_students.txt 中有 10,000 行。我的问题是:
- 我是否读取 enrolled_students.txt 中的每一行并逐个解析其他 100 个文件以找到匹配项?这似乎是处理这些数据的糟糕方式。有更快的方法吗?
- 我可以在并行模式(多线程)下执行这个进程吗?
谢谢,
汉斯
我会将您的问题视为:如何高效地执行两个文件的 "join" 操作,这里是答案。
实际上Unix中有一个join
命令。
http://linux.die.net/man/1/join
假设你有两个文件,student 和 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 块和运行 并行加入命令。这样,您就可以利用多核的力量。
您在此处尝试执行的操作类似于数据库引擎在将来自两个 table 的数据连接在一起时必须执行的操作。数据库引擎通常有许多不同的连接计划可供选择,它会尝试根据它对每个 table 中数据的了解来选择最好的一个。
同样适用于你。加入数据的方法有多种,最佳方法取决于每个输入文件的大小、是否预先排序等因素。
一些可能的方法:
A 'Nested Loop',您可以在其中读取 enrolled_students.txt 文件的每一行,并针对其中的每一行遍历其他文件以找到匹配项。不太可能很快,如果文件太大而无法使用任何其他解决方案,您可能只会选择此选项。
A 'Hash Join',您可以在其中将要连接的数据的一半(在您的示例中,可能是 name_of_country.txt)读取到由哈希索引的数据结构中.然后对于其他文件的每一行,您可以在散列中查找相应的行。这可以是相当高的性能,只要有足够的内存来同时存储两组数据中的至少一组。
如果两个文件都按某种排序顺序,根据相同的键排序,您也许可以使用 'Merge Join'。这是您同时从两个文件中读取行的地方,将记录匹配在一起就像拉链中的牙齿。
上面假设了一个简单的情况,其中有两个数据文件必须合并。您的问题涉及 100 个不同的 name_of_country.txt 文件,这可能会使事情复杂化。
关于您的第二个问题——您能否使用并行处理——这可能仅在处理受 CPU 约束时才有用。除非您发现它实际上是 CPU 绑定,否则可能无法保证生成分叉或线程解决方案的复杂性。
最后 - 如果您对同一数据进行多次分析 运行,建议将数据导入真实数据库并使用该 运行 查询。这将为您节省大量编码工作。
我有一个文件(暂且称之为 enrolled_students.txt)需要用 Perl 阅读。该文件每行都有数据,因此需要参考其他文件以获取更多信息。
例如,主数据库会有名称和地址。但是根据每个人的国籍,我必须参考其他文件(按国家排序)才能找到匹配的姓名、国籍和家庭住址。
假设我有 100 个 name_of_country.txt 文件,我的 enrolled_students.txt 中有 10,000 行。我的问题是:
- 我是否读取 enrolled_students.txt 中的每一行并逐个解析其他 100 个文件以找到匹配项?这似乎是处理这些数据的糟糕方式。有更快的方法吗?
- 我可以在并行模式(多线程)下执行这个进程吗?
谢谢, 汉斯
我会将您的问题视为:如何高效地执行两个文件的 "join" 操作,这里是答案。
实际上Unix中有一个join
命令。
http://linux.die.net/man/1/join
假设你有两个文件,student 和 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 块和运行 并行加入命令。这样,您就可以利用多核的力量。
您在此处尝试执行的操作类似于数据库引擎在将来自两个 table 的数据连接在一起时必须执行的操作。数据库引擎通常有许多不同的连接计划可供选择,它会尝试根据它对每个 table 中数据的了解来选择最好的一个。
同样适用于你。加入数据的方法有多种,最佳方法取决于每个输入文件的大小、是否预先排序等因素。
一些可能的方法:
A 'Nested Loop',您可以在其中读取 enrolled_students.txt 文件的每一行,并针对其中的每一行遍历其他文件以找到匹配项。不太可能很快,如果文件太大而无法使用任何其他解决方案,您可能只会选择此选项。
A 'Hash Join',您可以在其中将要连接的数据的一半(在您的示例中,可能是 name_of_country.txt)读取到由哈希索引的数据结构中.然后对于其他文件的每一行,您可以在散列中查找相应的行。这可以是相当高的性能,只要有足够的内存来同时存储两组数据中的至少一组。
如果两个文件都按某种排序顺序,根据相同的键排序,您也许可以使用 'Merge Join'。这是您同时从两个文件中读取行的地方,将记录匹配在一起就像拉链中的牙齿。
上面假设了一个简单的情况,其中有两个数据文件必须合并。您的问题涉及 100 个不同的 name_of_country.txt 文件,这可能会使事情复杂化。
关于您的第二个问题——您能否使用并行处理——这可能仅在处理受 CPU 约束时才有用。除非您发现它实际上是 CPU 绑定,否则可能无法保证生成分叉或线程解决方案的复杂性。
最后 - 如果您对同一数据进行多次分析 运行,建议将数据导入真实数据库并使用该 运行 查询。这将为您节省大量编码工作。