我在 mysql 中有几个非常大的表(数百万行),我需要将它们加载到我的 perl 脚本中。
然后我们对数据进行一些自定义处理,并将其聚合成一个散列。不幸的是,这种自定义处理不能在 MySQL 中实现。
这是一个快速的伪代码。
my @data;
for my $table_num(@table_numbers){
my $sth = $dbh->prepare(...);
$sth->execute();
$sth->bind_columns(\my($a,$b,$c,...));
while(($sth->fetch()){
$data[$table_num]{black_box($a)}{secret_func($b)}+=$c;
}
}
my $x = $#data + 1;
for my $num (@table_numbers){
for my $a (keys %{$data[$num]}){
for my $b (keys %{$data[$num]{$a}){
$data[$x]{$a}{$b} += $data[$num]{$a}{$b};
}
}
}
现在,第一个循环每次迭代可能需要几分钟才能运行,所以我正在考虑可以并行运行它们的方法。我之前看过使用 Perl 线程,但它们似乎只是同时运行几个 perl 解释器,而且我的脚本已经使用了大量内存,合并数据似乎没有问题。此外,在这个阶段,脚本并没有使用很多 CPU。
我一直在考虑可能使用 Coro 线程,但似乎会有一个学习曲线,加上我当前代码的相当复杂的集成。我想知道走这条路是否有可能获得任何收益。有没有更好的方法来处理这样的多线程代码。我不能再使用我的代码已经使用的内存了。还有什么我可以在这里做的吗?
不幸的是,在 MySQL 中进行聚合不是一种选择,并且用不同的语言重写代码会太耗时。我知道使用数组而不是哈希可能会使我的代码更快/使用更少的内存,但这同样需要对大型脚本进行重大重写。
编辑:以上是伪代码,实际逻辑要复杂得多。分桶基于几个 db 表,以及更多的输入,然后只是 $a 和 $b。预先计算它们是不切实际的,因为有数万亿种可能的组合。主要目标是如何让 perl 脚本运行得更快,而不是如何修复 SQL 部分的事情。这需要更改数据在实际服务器中的存储和索引方式。这会影响很多其他代码。还有其他人致力于进行这些优化。我目前的目标是尝试在不更改任何 sql 的情况下使代码更快。