【问题标题】:How to optimize this script performing INSERTS into a database?如何优化在数据库中执行 INSERTS 的脚本?
【发布时间】:2019-12-30 07:01:32
【问题描述】:

所以我已经完成了一个脚本,它将数据插入 mysql 表并将这些文件移动到一个目录中,直到所有文件都没有。大约有 51 个文件,完成执行大约需要 9 秒。所以我的问题是。有没有更好的方法来加快执行过程?

代码是

our $DIR="/home/aimanhalim/LOG";
our $FILENAME_REGEX = "server_performance_";
# mariaDB config hash
our %db_config = ( "username"=>"root", "password"=> "", "db"=>"Top_Data", "ip" => "127.0.0.1", "port" => "3306");
main();

exit;


sub main()
{
    my $start = time();
   print "Searching file $FILENAME_REGEX in $DIR...\n";
   opendir (my $dr , $DIR) or die "<ERROR> Cannot open dir: $DIR \n";
   while( my $file = readdir $dr )
   {
      print "file in $DIR: [$file]\n";
      next if (($file eq ".") || ($file eq "..") || ($file eq "DONE"));   



      #Opening The File in the directory
      open(my $file_hndlr, "<$DIR/$file");

      #Making Variables.
      my $line_count = 0;
      my %data = ();
      my $dataRef = \%data;
      my $move = "$DIR/$file";
      print "$file\n";
      while (<$file_hndlr>) 
      { 
         my $line = $_;  
         chomp($line);
         print "line[$line_count] - [$line]\n";
         if($line_count == 0)
         {
            # get load average from line 0
            ($dataRef) = get_load_average($line,$dataRef);

            print Dumper($dataRef);

         }
         elsif ($line_count == 2)
         {

          ($dataRef) = get_Cpu($line,$dataRef);
          print Dumper($dataRef);

         }

$line_count++;
      }

      #insert db
      my ($result) = insert_record($dataRef,\%db_config,$file);
      my $Done_File="/home/aimanhalim/LOG/DONE";


sub insert_record(){

 my($data,$db_config,$file)=@_;
 my $result = -1; # -1 fail;  0 - succ

  # connect to db
  # connect to MySQL database
  my $dsn = "DBI:mysql:database=".$db_config->{'db'}.";host=".$db_config->{'ip'}.";port=".$db_config->{'port'};
my $username = $db_config->{'username'};
my $password = $db_config->{'password'};

my %attr = (PrintError=>0,RaiseError=>1 );
my $dbh = DBI->connect($dsn,$username,$password,\%attr) or die $DBI::errstr;

print "We Have Successfully Connected To The Database \n";

  $stmt->execute(@param_bind);
  ****this line is insert data statement***
  $stmt->finish();
    print "The Data Has Been Inserted Successfully\n";
  $result = 0;
  return($result);

  # commit
  $dbh->commit();
  # return succ / if fail rollback and return fail
  $dbh->disconnect();

}
exit;

编辑

这几乎是我的代码,在这里和那里进行了一些狙击。

我试图将“insert_record”放在评论#insert db 下方,但我认为这无济于事:U

【问题讨论】:

  • 是的,有办法。
  • @ssr1012 对不起,我编辑回帖子
  • @Сухой27 如果是这样怎么办?
  • 事实上,您正在以可能的最慢方式进行操作,为您插入的每一行打开一个新的数据库连接。你可能会喜欢我的演讲Load Data Fast!

标签: mysql perl


【解决方案1】:

您正在为要插入的每个文件连接到数据库(如果我正确阅读了您的代码,似乎缺少一个右大括号,它实际上不会编译)。打开新的数据库连接(相对而言)很慢。

在插入第一个文件之前打开连接一次,然后将其重新用于后续插入数据库中。将最后一个文件插入数据库后关闭连接。这应该会给你一个显着的加速。

(根据数据量,9秒实际上可能还不错;但由于没有这方面的信息,所以很难说)。

【讨论】:

  • 在脚本中没有断开连接和提交是不是很奇怪?因为当我有这些东西时,它会给我一个分段错误(核心转储)的错误,但是当我删除它时......它工作正常
  • 您应该仍然能够在单个连接中处理多个事务。根据您的要求,插入所有数据后只提交一次可能就足够了
  • 但问题是即使没有 commit 和 disconnect 语句也可以正常工作
  • 一旦你的程序终止,任何打开的资源(如数据库连接、文件句柄)都会自动关闭。我假设没有任何错误,任何打开的交易都会自动提交。
  • @MiteMiteKyle 也可能是,连接会自动创建一个只能提交一次的事务。连续的commit 可能会产生错误(或段错误?看起来有点奇怪,但很好)如果您想要多个事务,则必须手动创建它们(重用现有连接)。
猜你喜欢
  • 1970-01-01
  • 2012-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
相关资源
最近更新 更多