1

Webサーバーのcronにスクリプトがあり、毎晩実行する必要があります。cronジョブでWebサーバーによって設定された制限時間を超えたため、最近実行を停止しました。以前は問題なく動作していました。手動で実行したときはいつでも、非常に高速でした(5分未満)。突然、30分以上かかります。

スクリプトは基本的にMySQLデータベースを更新します。彼らによると、DBは約60MBです。私はこの情報を見つけることができないようですが、それは合理的なようです(私が毎晩サーバーに転送するファイルは約2MBですが)。

私は自分のDBを最適化するために提案された手順を実行しましたが、実際には何も起こりませんでした。スクリプトの実行にはまだ時間がかかります。スクリプトが行うのは、DBからすべてを削除し、更新されたインベントリを再度入力することだけです。

そのため、別のウィンドウでスクリプトを実行しながら、1つのPuttyウィンドウで「showfullprocesslist」を実行しています。「showfullprocesslist」には、2、3の項目のみが表示され、どちらもその時点で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();
4

1 に答える 1

1

2 つの提案があります。

  1. (影響が少ない)TRUNCATEの代わりに使用するとDELETE、大幅に高速になり、自動インクリメント値を気にする必要がない場合に特に使いやすくなります。
  2. インサートのバッチで動作するように少し再構築します。通常、これを行うには、特定のサイズ (20 行程度から開始) のスタック変数を保持します。最初の 20 行では、スタックがいっぱいになります。しかし、20 行目では実際に挿入を実行し、スタックをリセットします。これによりどれだけパフォーマンスが向上するか、頭がおかしくなるかもしれません:-)

擬似コード:

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 を実行する「オーバーヘッド」に、極端に不均衡な量の作業が含まれていました (ネットワーク、等)

于 2012-07-17T06:50:11.127 に答える