正常情况下,判断数据集中是否出现id
的最快方法是使用散列法,因此我将使用id
作为关键字并将其余列的MD5校验和或CRC作为存储在那把钥匙。如果你的数据有很多列,这应该可以缓解内存压力。我为什么这么想?因为你说你有数百万条记录的GB数据,所以我推断每条记录的大小必须是千字节的数量 - 即相当宽。
所以,我能合成的在Perl 13M旧值的哈希和15M新值的哈希,然后找到添加,更改,如下面取出。
#!/usr/bin/perl
use strict;
use warnings;
# Set $verbose=1 for copious output
my $verbose=0;
my $million=1000000;
my $nOld=13*$million;
my $nNew=15*$million;
my %oldHash;
my %newHash;
my $key;
my $cksum;
my $i;
my $found;
print "Populating oldHash with $nOld entries\n";
for($i=1;$i<=$nOld;$i++){
$key=$i-1;
$cksum=int(rand(2));
$oldHash{$key}=$cksum;
}
print "Populating newHash with $nNew entries\n";
$key=$million;
for($i=1;$i<=$nNew;$i++){
$cksum=1;
$newHash{$key}=$cksum;
$key++;
}
print "Part 1: Finding new ids (present in newHash, not present in oldHash) ...\n";
$found=0;
for $key (keys %newHash) {
if(!defined($oldHash{$key})){
print "New id: $key, cksum=$newHash{rkey}\n" if $verbose;
$found++;
}
}
print "Total new: $found\n";
print "Part 2: Finding changed ids (present in both but cksum different) ...\n";
$found=0;
for $key (keys %oldHash) {
if(defined($newHash{$key}) && ($oldHash{$key}!=$newHash{$key})){
print "Changed id: $key, old cksum=$oldHash{$key}, new cksum=$newHash{$key}\n" if $verbose;
$found++;
}
}
print "Total changed: $found\n";
print "Part 3: Finding deleted ids (present in oldHash, but not present in newHash) ...\n";
$found=0;
for $key (keys %oldHash) {
if(!defined($newHash{$key})){
print "Deleted id: $key, cksum=$oldHash{$key}\n" if $verbose;
$found++;
}
}
print "Total deleted: $found\n";
这需要53秒在我的iMac上运行。
./hashes
Populating oldHash with 13000000 entries
Populating newHash with 15000000 entries
Part 1: Finding new ids (present in newHash, not present in oldHash) ...
Total new: 3000000
Part 2: Finding changed ids (present in both but cksum different) ...
Total changed: 6000913
Part 3: Finding deleted ids (present in oldHash, but not present in newHash) ...
Total deleted: 1000000
出于测试的目的,我从0..12,999,999在oldHash
运行键和按键在newHash
运行从1,000,000..16,000,000那么我可以很容易地知道,如果它的工作,因为新的键应该是13,000,000..16,000,000和删除的键应该是0..999,999。我也使checksums
在0和1之间交替,这样50%的重叠ID应该看起来不同。
已经在一个相对简单的方式来完成它,现在我可以看到,你只需要校验部分找到改变的ID,这样你就可以做1部分和第3无校验以节省内存。在加载数据时,您也可以一次执行第2部分的一个元素,因此您不需要将所有旧的和所有新的ID都预先加载到内存中。相反,当您将另一组ID传输到内存中时,您将加载较小的旧数据集和新数据集,然后逐个检查一个ID是否更改,这会降低对内存的要求。最后,如果这种方法有效,它可以很容易地在C++中重新完成,例如,进一步加快速度并进一步减少内存需求。
我正在考虑将独特的id读入两个Perl哈希中 - 一个用于旧的旧哈希,另一个可能是每个记录的剩余字段的CRC/SHA校验和作为存储在哈希中的项目。检查通用/独特的会员资格应该非常快。尝试添加一个Perl标签也许。 –
你提到过关于文件大小。我可以知道速度是多少?意思是,你多久会得到这个后续文件。 –
每天约20K次 – user5121292