“show full processlist”显示没有占用时间的进程,但我的脚本需要太长时间

时间:2012-07-17 06:10:47

标签: mysql

我有一个脚本驻留在我的网络服务器的cron上,应该每晚运行。由于超过了网络服务器在cron作业上设置的时间限制,它最近已停止运行。它曾经运行良好。无论何时我手动运行它,它都非常快(不到5分钟)。突然间,它需要半个多小时。

该脚本基本上更新了MySQL数据库。根据他们的说法,数据库大约是60mb。我似乎无法找到这些信息,但它似乎是合理的(虽然我每晚转移到服务器的文件只有2mb左右。)

我已经采取了建议来优化我的数据库的步骤,但实际上没有任何结果。脚本运行仍需要很长时间。所有脚本都会删除数据库中的所有内容,并使用我们更新的库存再次填写。

所以现在我在一个Putty窗口上运行“show full processlist”,同时在另一个窗口中运行脚本。 “show full processlist”仅显示几个项目,这两个项目都显示为0。

mysql> show full processlist;
+-----------+--------------+--------------------+-------------------------+---------+------+-------+-----------------------+
| Id        | User         | Host               | db                      | Command | Time | State | Info                  |
+-----------+--------------+--------------------+-------------------------+---------+------+-------+-----------------------+
| 142841868 | purposely omitted | purposely omitted | purposely omitted_net_-_main | Sleep   |    0 |       | NULL                  |
| 142857238 | purposely omitted | purposely omitted | NULL                    | Query   |    0 | NULL  | show full processlist |
+-----------+--------------+--------------------+-------------------------+---------+------+-------+-----------------------+
2 rows in set (0.05 sec)

如果我继续快速使用show full processlist命令,偶尔我可以捕获此表中列出的其他内容但是下次运行时它们会消失。这向我表明他们正在快速处理!

所有人都有任何想法会出错吗?我对此很新:(

谢谢!

PS这是我的代码

#!/usr/bin/perl
use strict;
use DBI;
     my $host = 'PURPOSLEY OMITTED';
     my $db = 'PURPOSLEY OMITTED';
     my $db_user = 'PURPOSLEY OMITTED';
     my $db_password = "PURPOSLEY OMITTED";

my $dbh = DBI->connect("dbi:mysql:$db:$host", "$db_user", "$db_password");
$dbh->do("DELETE FROM main");
$dbh->do("DELETE FROM keywords");

open FH, "PURPOSLEY OMITTED" or die;

while (my $line = <FH>) {

my @rec = split(/\|/, $line);

print $rec[1].' : '.$rec[2].' : '.$rec[3].' : '.$rec[4].' : '.$rec[5].' : '.$rec[6].' : '.$rec[7];

$rec[16] =~ s/"//g;
$rec[17] =~ s/"//g;
$rec[13] =~ chomp($rec[13]);

my $myquery = "INSERT INTO main (medium, title, artist, label, genre, price, qty, catno,barcode,created,received,tickler,blurb,stockid) values (\"$rec[0]\",\"$rec[1]\",\"$rec[2]\",\"$rec[3]\",\"$rec[4]\",\"$rec[5]\",\"$rec[6]\",\"$rec[7]\",\"$rec[8]\",\"$rec[9]\",\"$rec[10]\",\"$rec[11]\",\"$rec[12]\",\"$rec[13]\")"; 

$dbh->do($myquery);

$dbh->do("INSERT IGNORE INTO keywords VALUES (0, '$rec[2]','$rec[13]')");
$dbh->do("INSERT LOW_PRIORITY IGNORE INTO keywords VALUES (0, \"$rec[1]\", \"$rec[13]\")");

print "\n";
}
close FH;

$dbh->disconnect();

1 个答案:

答案 0 :(得分:1)

我有两点建议:

  1. (影响力较小)使用TRUNCATE代替DELETE,它明显更快,并且在您不需要担心自动递增值时特别容易使用。
  2. 轻微重组以分批处理插入物。通常我通过保持给定大小的堆栈变量(从20行开始)来做到这一点,对于前20行,它只是填充堆栈;但在第20行它实际上也执行插入并重置堆栈。它可能让你觉得这可以提高性能: - )
  3. 的伪代码:

    const buffer_size = 20
    while(row) {
      stack.addvalues(row.values)
      if(stack.size >= buffer_size) {
        // INSERT INTO mytable (fields) VALUES stack.all_values()
        stack.empty()
      }
    

    然后播放“缓冲”大小。我已经看过脚本,将缓冲区调整到100-200行以上,一次加速大量进口(即执行单个INSERT的“开销”涉及到大量不成比例的工作量(网络,等)