我目前正在尝试改进一个现有机制(用于比较两个数据源中的数据,使用perl5实现),希望改用perl6。
我的目标数据量范围是约20-30 GB的未压缩平面文件。 就行数而言,一个文件可以包含从1800万到2800万行的任何位置。 每行大约有40-50列。
我每天都要进行这种类型的数据对账,从文件中读取并填充哈希表可能需要约10分钟。读取两个文件并填充哈希表需要约20分钟。
比较过程需要约30-50分钟,包括迭代哈希表、收集所需结果和写入输出文件(csv、psv)。
总体而言,在一个32核双Xeon CPU服务器上,处理整个流程可能需要30分钟到60分钟,包括间歇性的服务器负载。
现在我正试图进一步缩短总处理时间。
以下是我目前使用perl5的单线程方法:
- 逐个从2个来源(假设为s1和s2)获取数据,并根据键值对填充哈希表。数据源可以是扁平的csv或psv文件或数据库查询数组结果,通过DBI客户端。数据始终未排序。
- 具体来说,我逐行读取文件,分割字段,并选择键值对的所需索引插入哈希表。
- 在收集数据并填充具有所需键/值对的哈希表之后,开始比较和收集结果(主要比较s2相对于s1缺少或不同的内容,反之亦然)。
- 将输出转储到Excel文件(如果行数大约为~1百万或更多,则非常昂贵)或简单的CSV文件中(便宜操作,首选方法)。
我想知道是否可以并行执行第一步,即同时从两个来源收集数据并填充全局哈希表,然后进行比较和转储输出?
Perl6能提供哪些选项来处理这种情况?我已经阅读了关于使用perl6进行并发、异步和并行操作的文章,但我不确定哪个可以在这里帮助我。
我真的很感激任何一般性的指导。我希望我已经解释了我的问题,但可悲的是我没有什么可以展示的到目前为止我做了什么?,原因是我刚开始解决这个问题。我只能看到单线程方法,需要一些帮助。
谢谢。
编辑
由于社区认为我的现有问题陈述“太广泛”,请允许我尝试以下突出我的问题点:
- 如果可能,我想利用所有32个核心进行文件比较。我只是无法想出一个策略或初始想法。
- Perl6提供了哪些新技术或适用于解决此类问题的技术。
- 如果我生成2个进程来读取文件和收集数据,则是否可能将结果作为数组或哈希返回?
- 是否可能并行比较(存储在哈希表中的数据)?
您可以参考下面的代码来了解
package COMP;
use strict;
use Data::Dumper;
sub comp
{
my ($data,$src,$tgt) = @_;
my $result = {};
my $ms = ($result->{ms} = {});
my $mt = ($result->{mt} = {});
my $diff = ($result->{diff} = {});
foreach my $key (keys %{$data->{$src}})
{
my $src_val = $data->{$src}{$key};
my $tgt_val = $data->{$tgt}{$key};
next if ($src_val eq $tgt_val);
if (!exists $data->{$tgt}{$key}) {
push (@{$mt->{$key}}, "$src_val|NULL");
}
if (exists $data->{$tgt}{$key} && $src_val ne $tgt_val) {
push (@{$diff->{$key}}, "$src_val|$tgt_val")
}
}
foreach my $key (keys %{$data->{$tgt}})
{
my $src_val = $data->{$src}{$key};
my $tgt_val = $data->{$tgt}{$key};
next if ($src_val eq $tgt_val);
if (!exists $data->{$src}{$key}) {
push (@{$ms->{$key}},"NULL|$tgt_val");
}
}
return $result;
}
1;
如果有人想尝试一下,这里是样例输出和使用的测试脚本。
脚本输出:
[User@Host:]$ perl testCOMP.pl
$VAR1 = {
'mt' => {
'Source' => [
'source|NULL'
]
},
'ms' => {
'Target' => [
'NULL|target'
]
},
'diff' => {
'Sunday_isit' => [
'Yes|No'
]
}
};
测试脚本
[User@Host:]$ cat testCOMP.pl
#!/usr/bin/env perl
use lib $ENV{PWD};
use COMP;
use strict;
use warnings;
use Data::Dumper;
my $data2 = {
f1 => {
Amitabh => 'Bacchan',
YellowSun => 'Yes',
Sunday_isit => 'Yes',
Source => 'source',
},
f2 => {
Amitabh => 'Bacchan',
YellowSun => 'Yes',
Sunday_isit => 'No',
Target => 'target',
},
};
my $result = COMP::comp ($data2,'f1','f2');
print Dumper $result;
[User@Host:]$