2012-01-09 106 views
0

现在我有两个散列哈希值,我通过解析一个日志文件创建了1个哈希,我从SQL获取了1个哈希。我需要比较它们以确定日志文件中的记录是否已经存在于数据库中。现在我通过遍历每个元素来比较它们:比较哈希散列的最佳方法是什么?

foreach my $i(@record) 
{ 
    foreach my $a(@{$data}) 
    { 
     if ($i->{port} eq $a->{port} and $i->{name} eq $a->{name}) 
     { 
      print "match found $i->{name}, updating record in table\n"; 
     } 
     else 
     { 
      print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n"; 
      executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')"); 

     } 
    } 

} 

当然,随着数据库变大,这需要很长时间才能运行。有没有更有效的方法来做到这一点?我可以直接比较密钥吗?

+1

这样的声音应该在SQL中解决,而不是perl。当然,有一种方法可以在SQL中“更新或插入”? – TLP 2012-01-09 16:36:51

回答

0

如何使用数据::差异:

use Data:Difference qw(data_diff); 

my @diff = data_diff(\%hash_a, \%hash_b); 

@diff = (
    { 'a' => 'value', 'path' => [ 'data' ] }, # exists in 'a' but not in 'b' 
    { 'b' => 'value', 'path' => [ 'data' ] }, # exists in 'b' not in 'a' 
); 
2

你有超过哈希散列更多。您有两个列表,每个列表中的每个元素都包含散列哈希。因此,您必须将列表中的每个项目与另一个列表中的每个项目进行比较。你的算法的效率是O - 不是因为它是哈希散列,而是因为你将一个列表中的每一行与另一个列表中的每一行进行比较。

是否有可能通过您的列表,并将它们转换为由端口和名称键入的哈希值?这样,你通过每个列表一次来创建索引哈希,然后通过哈希一次来做比较。

my %record_hash; 
foreach my $record_item (@record) { 
    my $name = $record_item->{name}; 
    my $data = $record_item->{data} 
    my $record_hash{$name:$data} = \$record_item #Or something like this... 
} 

接下来,你会做同样为您数据列表:

例如,从记录中创建哈希

my %data_hash; 
foreach my $data_item (@{$data}) { 
    my $name = $data_item->{name}; 
    my $data = $data_item->{data} 
    my $data_hash{$name:$data} = \$data_item #Or something like this... 
} 

现在,你可以通过你的新创建散列只是一次:

foreach my $key (keys %record_hash) { 
    if (exists $data_hash{$key}) { 
     print "match found $i->{name}, updating record in table\n"; 
    } 
    else { 
     print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n"; 
     executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')"); 

    } 
} 

假设你有100一个列表中有0个元素,另一个列表中有500个元素。您的原始算法将不得不循环500 * 1000次(50万次)。通过创建索引散列,您必须循环2(500 + 1000)次(大约3000次)。

另一种可能性:既然您已经在使用SQL数据库,那么为什么不把它作为SQL查询呢。也就是说,不要获取记录。相反,通过您的数据,并为每个数据项获取记录。如果记录存在,则更新它。如果不是,则创建一个新的。这可能会更快,因为你没有把整个事情变成一个列表,以便把它变成一个哈希。

有一种方法可以直接对tie SQL databases进行哈希。这可能是一个好方法。

您使用的是Perl-DBI

+0

优秀的答案 – Richard 2012-01-10 09:40:16

+0

感谢您的回复,这是非常丰富的。我可能会尝试为您建议的每条记录创建一个散列。我也尝试使用SQL命令,如IF EXISTS,正如你在第二种可能性中提到的那样,但不能让它们正常工作。我想过的另一个想法是尝试使用通过解析日志文件收集的数据创建临时表,然后连接两个表来查看哪些记录存在,然后添加不存在的记录。 – cottageDog 2012-01-10 14:43:25

+0

我最后在MySQL上使用存储过程来根据记录的存在插入或更新。 – cottageDog 2012-01-11 16:25:05

相关问题