Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex perl正则表达式大数据性能_Regex_Performance_Algorithm_Perl - Fatal编程技术网

Regex perl正则表达式大数据性能

Regex perl正则表达式大数据性能,regex,performance,algorithm,perl,Regex,Performance,Algorithm,Perl,1.)我从数据库中读取了大量数据(约1000万条记录)。 2.)对于每个记录,我搜索并替换我拥有的大约500个正则表达式。 3.)应用所有500个正则表达式后,记录将写入文件,然后处理下一条记录 性能瓶颈是对从数据库获取的每条记录应用500个正则表达式 以下是相关代码块: #normalizing the addresses fetched... this may take awhile while(my @row = $queryHandle->fetchrow_array())

1.)我从数据库中读取了大量数据(约1000万条记录)。 2.)对于每个记录,我搜索并替换我拥有的大约500个正则表达式。 3.)应用所有500个正则表达式后,记录将写入文件,然后处理下一条记录

性能瓶颈是对从数据库获取的每条记录应用500个正则表达式

以下是相关代码块:

#normalizing the addresses fetched... this may take awhile
    while(my @row = $queryHandle->fetchrow_array())
    {
        #extract data from record
        $accountKey = @row[0];
        $addressLine1 = @row[1];
        $addressLine2 = @row[2];

        #iterate through all the regular expressions I have stored (about 500)
        for my $regexRef (@regexesList)
        {
            #get regular expression hash object
            my %regexObj = %{$regexRef};
            my $regexPattern = $regexObj{pattern}; #the regex pattern
            my $regexOutput = $regexObj{output}; #the replacement string

            #first remove all special characters leaving only numbers and alphabets
            $addressLine1 =~ s/[^A-Za-z0-9 ]//g;
            $addressLine2 =~ s/[^A-Za-z0-9 ]//g;

            #now standardize the addresses
            $addressLine1 =~ s/$regexPattern/$regexOutput/ig;
            $addressLine2 =~ s/$regexPattern/$regexOutput/ig;
        }

        my $normalizedAddress = lc($addressLine1 . $addressLine2);
        $normalizedAddress =~ s/\s+//g; #remove all white space

        print $dataFileHandle "${normalizedAddress}\n";
        $rowCount++;
    }
这是工作代码,但性能非常差。目前该脚本已经运行了2.5个小时,已经向输出文件写入了313万条记录,还有大约700万条记录,哈哈

这是最好的吗?还有其他更快或更慢的方法吗?也许先将每一行写入一个文件,然后在整个文件上运行每个正则表达式


在我尝试上述替代方案之前,我想知道是否有更好的方法来实现这一点。首先,您正在进行大量不必要的ref和deref。因此,在@regexesList中有一个regex列表,其中显然充满了hashrefs。在迭代时,对每个hashref进行解引用,这会在内存中复制它,然后从复制的哈希中取出项目

所以,第一条建议是,不要这样做。这将代码中的for循环简化为:

for my $regexRef (@regexesList)
{
    #first remove all special characters leaving only numbers and alphabets
    $addressLine1 =~ s/[^A-Za-z0-9 ]//g;
    $addressLine2 =~ s/[^A-Za-z0-9 ]//g;

    #now standardize the addresses
    $addressLine1 =~ s/$regexRef->{pattern}/$regexRef->{output}/ig;
    $addressLine2 =~ s/$regexRef->{pattern}/$regexRef->{output}/ig;
}

接下来,尝试将更多工作卸载到数据库中。当我使用mysql进行这类工作时,我会将尽可能多的简单任务卸载到数据库中,因为这些类型的字符串函数在那里要快得多。我使用了大量的LOWER()、CONCAT()、CONCAT_WS()和REPLACE(),它们在这里也可以为您服务。

首先,您正在进行大量不必要的ref和deref。因此,在@regexesList中有一个regex列表,其中显然充满了hashrefs。在迭代时,对每个hashref进行解引用,这会在内存中复制它,然后从复制的哈希中取出项目

所以,第一条建议是,不要这样做。这将代码中的for循环简化为:

for my $regexRef (@regexesList)
{
    #first remove all special characters leaving only numbers and alphabets
    $addressLine1 =~ s/[^A-Za-z0-9 ]//g;
    $addressLine2 =~ s/[^A-Za-z0-9 ]//g;

    #now standardize the addresses
    $addressLine1 =~ s/$regexRef->{pattern}/$regexRef->{output}/ig;
    $addressLine2 =~ s/$regexRef->{pattern}/$regexRef->{output}/ig;
}

接下来,尝试将更多工作卸载到数据库中。当我使用mysql进行这类工作时,我会将尽可能多的简单任务卸载到数据库中,因为这些类型的字符串函数在那里要快得多。我使用了大量的LOWER()、CONCAT()、CONCAT_WS()和REPLACE(),它们在这里也可以为您服务。

您每次都要重新分析500-600个正则表达式,这需要时间

    $addressLine1 =~ s/$regexPattern/$regexOutput/ig; # Interpolate and reparse
下面是一个概念证明,它构建了一个匿名子例程,其中包含文本代码中的正则表达式,而不是每次都从变量进行解释

这表明性能提高了10倍

use strict;
use warnings;

use Benchmark;

my @regexesList = map {{pattern => "foo$_", output => "bar$_"}} (1..600);

my $string1 = 'a' x 100;
my $string2 = 'b' x 100;

# Original code
sub original {
    my ($regexesList, $addressLine1, $addressLine2) = @_;

    #iterate through all the regular expressions I have stored (about 500)
    for my $regexRef (@regexesList) {
        #get regular expression hash object
        my %regexObj = %{$regexRef};
        my $regexPattern = $regexObj{pattern}; #the regex pattern
        my $regexOutput = $regexObj{output}; #the replacement string

        #now standardize the addresses
        $addressLine1 =~ s/$regexPattern/$regexOutput/ig;
        $addressLine2 =~ s/$regexPattern/$regexOutput/ig;
    }

    my $normalizedAddress = lc($addressLine1 . $addressLine2);
    $normalizedAddress =~ s{\s+}{}g; #remove all white space

    return $normalizedAddress;
}

# Build an anonymous subroutine to do all of the regex translations:
my $regex_code = "s/\\s+//g;\n";
for (@regexesList) {
    $regex_code .= "s/$_->{pattern}/$_->{output}/ig;\n";
}
my $code = <<"END_CODE";
    sub {
        my \@address = \@_;
        for (\@address) {
            $regex_code
        }
        return lc join '', \@address;
     }
END_CODE
my $address_sub = eval $code;
if ($@) {
    die "Invalid code $code: $@";
}

# Benchmark these two calling methods:
timethese(10000, {
    'original' => sub { original(\@regexesList, $string1, $string2) },
    'cached'   => sub { $address_sub->($string1, $string2) },
});
此外,您不必要地应用了这个正则表达式
s/[^A-Za-z0-9]//g用于循环的每个迭代。这是不必要的,可以在循环之外应用


可能还有其他可以改进的地方,但您必须利用自己的力量来找到它们,因为这并不是这样做的真正目的。

您每次都要重新分析500-600个正则表达式,这需要时间

    $addressLine1 =~ s/$regexPattern/$regexOutput/ig; # Interpolate and reparse
下面是一个概念证明,它构建了一个匿名子例程,其中包含文本代码中的正则表达式,而不是每次都从变量进行解释

这表明性能提高了10倍

use strict;
use warnings;

use Benchmark;

my @regexesList = map {{pattern => "foo$_", output => "bar$_"}} (1..600);

my $string1 = 'a' x 100;
my $string2 = 'b' x 100;

# Original code
sub original {
    my ($regexesList, $addressLine1, $addressLine2) = @_;

    #iterate through all the regular expressions I have stored (about 500)
    for my $regexRef (@regexesList) {
        #get regular expression hash object
        my %regexObj = %{$regexRef};
        my $regexPattern = $regexObj{pattern}; #the regex pattern
        my $regexOutput = $regexObj{output}; #the replacement string

        #now standardize the addresses
        $addressLine1 =~ s/$regexPattern/$regexOutput/ig;
        $addressLine2 =~ s/$regexPattern/$regexOutput/ig;
    }

    my $normalizedAddress = lc($addressLine1 . $addressLine2);
    $normalizedAddress =~ s{\s+}{}g; #remove all white space

    return $normalizedAddress;
}

# Build an anonymous subroutine to do all of the regex translations:
my $regex_code = "s/\\s+//g;\n";
for (@regexesList) {
    $regex_code .= "s/$_->{pattern}/$_->{output}/ig;\n";
}
my $code = <<"END_CODE";
    sub {
        my \@address = \@_;
        for (\@address) {
            $regex_code
        }
        return lc join '', \@address;
     }
END_CODE
my $address_sub = eval $code;
if ($@) {
    die "Invalid code $code: $@";
}

# Benchmark these two calling methods:
timethese(10000, {
    'original' => sub { original(\@regexesList, $string1, $string2) },
    'cached'   => sub { $address_sub->($string1, $string2) },
});
此外,您不必要地应用了这个正则表达式
s/[^A-Za-z0-9]//g用于循环的每个迭代。这是不必要的,可以在循环之外应用


可能还有其他可以改进的地方,但您必须利用自己的力量来找到它们,因为这并不是这样做的真正目的。

转到codereview,准确解释您正在尝试做什么以及为什么需要应用500 regex。这是为了标准化用户地址,如St.,str.,street,road,rd.,drive,博士等等。USPS邮政地址标准的完整列表接近600。USPS对此有足够的支持。@friedo该API的地址验证需要批准,我的时间很短=(次要建议:
tr/A-Za-z0-9//dc
将比
s/[^A-Za-z0-9]更快)//g
。转到codereview,准确解释您正在尝试做什么以及为什么需要应用500正则表达式。这是为了标准化用户地址,如St.,str.,street,road,rd.,drive,dr.等。USPS邮政地址标准的完整列表接近600。USPS对此有详细说明。@friedo该API要求的地址验证ires批准和我的时间不足=(次要建议:
tr/A-Za-z0-9//dc
将比
s/[^A-Za-z0-9]更快)//g
。谢谢你的提示!我是一个Perl新手,匿名子例程中有一行让我难堪的代码,$regex\u代码是如何应用于for循环中的\@地址的?请原谅noob问题你可以打印出
$code
的值来查看我完整构建的匿名子例程。它使用循环
(@地址)
将每个地址行分配给全局变量
$\
。然后每个正则表达式替换
s/../../ig
在默认情况下在
$\
上工作。啊,我不知道正则表达式在默认情况下在$上工作,即使$未写入代码块。非常感谢!看起来我在perlthanks f上还有更多的阅读要做或者提示!我是Perl的新手,在匿名子例程中有一行让我感到困惑,$regex_代码是如何应用于for循环中的\@address的?请原谅noob问题您可以打印出
$code
的值来查看我完整构建的匿名子例程。它使用循环
for(@address)
将每个地址行分配给全局变量
$\u
。然后每个正则表达式替换
s/../…/ig
在默认情况下在
$\u
上工作。啊,我不知道正则表达式在de下正在处理$