需要加速 PERL 脚本(每行输入需要 1 秒)[关闭]

Posted

技术标签:

【中文标题】需要加速 PERL 脚本(每行输入需要 1 秒)[关闭]【英文标题】:Need to speedup PERL script(Takes 1 sec for every Row to input) [closed] 【发布时间】:2021-12-09 13:15:00 【问题描述】:

下面的这个 Perl 脚本每行插入需要 1 秒,当要插入很多行时,它的效率非常低。如果输入文件有超过 1,000,000 行,此脚本将需要大约 1,000,000 行。 12 天插入。

样本数据(行)

/mnt/SYN/TEST-Dropbox/Documents/TempBM/10-07-19.docx
/mnt/SYN/CLIENT-DROPBOX-GSUITE/Dropbox-TEST/My Mac (TEST-iMac-Pro.local)/Documents/TempBM/10-07-19.docx

/mnt/SYN/TEST-Dropbox/Documents/TO BE TRANSCRIBED LATER/LASTNAME, FIRSTNAME, Tape 2 (Inaudible)/LASTNAME, FIRSTNAME, TAPE 2 SIDE B (Inaudible).mp3
/mnt/SYN/CLIENT-SYNOLOGY/A. TO BE TRANSCRIBED/*TO BE TRANSCRIBED LATER/LASTNAME, FIRSTNAME, Tape 2 (Inaudible)/LASTNAME, FIRSTNAME, TAPE 2 SIDE B (Inaudible).mp3
/mnt/SYN/CLIENT-SYNOLOGY/DropboxBackup/*TO BE TRANSCRIBED LATER/LASTNAME, FIRSTNAME, Tape 2 (Inaudible)/LASTNAME, FIRSTNAME, TAPE 2 SIDE B (Inaudible).mp3
/mnt/SYN/CLIENT-DROPBOX-GSUITE/Dropbox-TEST/My Mac (TEST-iMac-Pro.local)/Documents/TO BE TRANSCRIBED LATER/LASTNAME, FIRSTNAME, Tape 2 (Inaudible)/LASTNAME, FIRSTNAME, TAPE 2 SIDE B (Inaudible).mp3

脚本

use strict;
use warnings;
use DateTime;
use DBI;

my $inputfile = shift || "-1";
my $startline = shift || "-1";
my $endline = shift || "-1";

if (($inputfile eq "-1") || ($startline eq "-1") || ($endline eq "-1") )
        print "USAGE: $0 <name_of_file.txt> START_LINE_NUMBER END_LINE_NUMBER\n";


my $group_id = 1;
my $linecounter = 0;
my $dsn = "DBI:MariaDB:Potato1";
my $username = "root";
my $password = "";

my %attr = ( PrintError=>1, RaiseError=>1);
my $dbh = DBI->connect($dsn, $username, $password, \%attr);
print "Connected to mysql database";

my $sql = "INSERT INTO GMCfiles_tbl(file_id, file_add_date, group_id, filename, status, status_author, status_date) VALUES (?, ?, ?, ?, ?, ?, ?)";
my $stmt = $dbh->prepare($sql);
open(INFILE, "< $inputfile") or die "Could NOT open $inputfile";

while(<INFILE>) 
    my $data = $_;
    $linecounter++;
        if (length($data) < 5) 
            $group_id++;
            sleep 2;
         else 
            my $file_add_date = DateTime->now;
            my $filename = $data;
            my $status = "New";
            my $status_author="";
            my $status_date = DateTime->now;

            if ( ($linecounter >= $startline) && ($linecounter <= $endline) ) 
                if ($stmt->execute($linecounter, $file_add_date, $group_id, $filename, $status, $status_author, $status_date))
                    print "Row inserted successfully LINE $linecounter -- GROUP $group_id\n";
                
                if ( ($linecounter > 0) && (($linecounter % 10) == 0) ) 
                    print "We're processing LINE $linecounter\n";
                
            
        


close(INFILE);
$stmt->finish();
$dbh->disconnect;

因为这个脚本会运行几天。有人能指出提高效率的方法吗?

【问题讨论】:

将所有插入包装在一个事务中? DBIx::Connector 是一个很好的事务管理包装器,或者只使用 DBI begin_work()commit() 方法。 微优化:您不需要在循环中创建两个不同的DateTime 对象。或者那些 $status$status_author 变量,当分配给它们的值永远不会改变时。使用文字或将它们提升到循环之外。 尝试运行你的程序并注释掉execute()方法调用。这将告诉您问题出在 perl 端还是 DB 端。乍一看,脚本不可能每行占用一秒钟。 您的代码中有一行sleep 2。这将使您的程序等待输入文件中少于 5 个字符(包括换行符)的每行 2 秒。你不知道吗? 【参考方案1】:

这个问题似乎有一个简单的解决方案。你的代码中有这个:

if (length($data) < 5) 
    $group_id++;
    sleep 2;

函数sleep 将休眠(等待、暂停)作为参数给出的秒数。在你的情况下,2秒。这适用于所有短于 5 个字符的行,给定 if 子句。

删除sleep 看看是否能解决您的问题。

【讨论】:

以上是关于需要加速 PERL 脚本(每行输入需要 1 秒)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何自动化ssh登录,其中perl脚本用户需要2个密码

Perl 简单的猜单词脚本

是否有 perl 5.005 核心模块可以将纪元秒数转换为日期时间字符串?

Perl - 验证网页表单中的汉字输入?

Perl 的反引号/系统给出“tcsetattr:输入/输出错误”

Perl入门