-1

私は現在、MySQLデータベースのデータ操作を含むプロジェクトに取り組んでいます。まず、同じマシンで実行されるperlスクリプトを使用していることをお伝えする必要があります。また、私が取り組んでいるテーブルについていくつかお話ししたいと思います。テーブルの作成は次のとおりです。

CREATE TABLE `deCoupled` (
    `AA` double NOT NULL DEFAULT '0',
     ...several other fields,
     KEY `AA` (`AA`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

データの処理方法を最適化するために、次のような一時テーブルを作成します。

CREATE TABLE `temp_deCoupled` AS SELECT * FROM `deCoupled` ORDER BY field1,field2,...,fieldN

データ操作に必要なauto_incrementキーフィールドを追加します。

ALTER TABLE `temp_deCoupled` ADD COLUMN MY_KEY INT NOT NULL AUTO_INCREMENT KEY
ALTER TABLE `temp_deCoupled` ADD INDEX (MY_KEY)

クエリでテーブルをスキャンするため、このようにテーブルを変更します

SELECT COUNT(`AA`), field1, field2,..., fieldN FROM `temp_deCoupled`
GROUP BY field1, field2,..., fieldN ORDER BY field1, field2,..., fieldN

MY_KEYフィールドに従ってレコードの更新を実行します。残念ながら、レコード数が約75000レコードの場合、デュアルコアCPUと2ギガのRAMを搭載したPCでは約75分かかります。また、データを操作するperlスクリプトは複雑な計算を行わないことをお伝えする必要があります。

MYSQLサーバーを調整しようとしましたが、my.cnfファイルを次のように更新しました。

key_buffer = 256M
sort_buffer_size = 128M
read_buffer_size = 64M
read_rnd_buffer_size = 64M
key_buffer_size = 128M
table_cache = 1024
query_cache_limit = 128M
query_cache_size = 128M
innodb_buffer_pool_size = 768M
innodb_thread_concurrency = 8
innodb_flush_method = o_DIRECT

スクリプトの実行時間を本当に短縮する必要があります。誰か提案できますか?

更新についてより正確に言うと、以下のコードのサンプルを投稿します。

$qSel = "SELECT COUNT(*), field1,..., fieldN FROM `temp_deCoupled` GROUP BY field1,..., fieldN ORDER BY field1,...,fieldN";
$stmt = $dbh->prepare($qSel);
$stmt->execute() or die "Error occurred: $DBI::errstr.\n";
while($stmt->fetch()) {
    .... *some code*...
    $q_sel_keys = "SELECT MY_KEY FROM `temp_deCoupled` WHERE field1 = value1 AND ... AND fieldN = valueN";
    $stmt1 = $dbh->prepare($q_sel_keys);
    $stmt1->execute() or die "Error occured: $DBI::errstr.\n";
    ...*some other code*...
    $q_Update_Records = "UPDATE `temp_deCoupled` SET field1=val_1,..., fieldN=val_N WHERE MY_KEY = key1 OR MY_KEY = key2 OR ... OR MY_KEY = keyN";
    $stmt1 = $dbh->prepare($q_Update_Records);
    $tmp_c = $stmt1->execute() or die "Error occured: $DBI::errstr.\n";
    ...*some final code*...
}

これがPerlでのデータ操作の(一般的な)本体です。

4

3 に答える 3

1

あなたはたくさんの情報を提供したようですが、必要な重要な情報(しゃれを許せば)ではありません。つまり、これほど時間がかかる更新は何をするのでしょうか。

75000の更新ステートメントを個別に実行している場合、これには長い時間がかかります。更新によって実行される操作が同じで、キーのみが異なる場合は、それらをグループ化してみてください。たとえば、次のようにします。

update temp_deCoupled set fieldx=..., fieldy=... where my_key in (?,?,?,?,...)

更新が大きく異なる最悪のシナリオでは、別のテーブルを使用して、更新に必要な情報を提供できます。たとえば、次の表があるとします。

create table foo ( id int primary key, bar double );

ここで、各バーにidに基づいて異なる値を掛け、乗数を保持する別のテーブルを作成し、スクリプトからの単一のリクエストにそれらを挿入してから、以下を更新する必要があります。

create temporary table foo_multiply ( id int primary key, mult double );
insert into foo_multiply values (1,123),(2,42),(3,666),...;
update foo inner join foo_multiply using (id) set foo.bar=foo.bar * foo_multiply.mult;

挿入ステートメントを1MB程度以下の行に分割することをお勧めします。極端な場合は、ファイルに挿入するデータを書き込んで、「LOADDATAINFILE」でロードしてください。

于 2012-08-27T23:09:50.300 に答える
0

デフォルトでは、MySQLドライバーは各ステートメントの後にデータベースへの変更をコミットします。これにより、多数の更新を行うときにパフォーマンスが最適化されないことがよくあります。

AutoCommitモードを無効にすると、パフォーマンスの問題が解決する可能性があります。しかし、@ ystshのアイデアと同様に、これはあなたが提供していない情報に基づいています。

于 2012-08-28T11:42:00.857 に答える
0

temp_deCoupledテーブルを次のように作成することで、実行時間を12分に短縮することができました。

CREATE TABLE `temp_deCoupled` ENGINE = MEMORY AS SELECT * FROM `deCoupled` ORDER BY field1,field2,...,fieldN

また、my.cnfで次の構成を行いました。

max_heap_table_size = 512M

ご関心をお寄せいただき、誠にありがとうございました。

于 2012-08-28T11:21:46.863 に答える