私はデータの大きなCSVファイルのインポートに取り組んできました。通常、100,000未満のレコード。私はPHPおよびMySQL(InnoDBテーブル)を使用しています。MySQLINSERT
sの前にいくつかのフィールドを変換し、テキスト処理を行うためにPHP (以下のコードのprocess_note_data()
の一部)。MySQLの_LOAD DATA
_は実行可能でなかったため、提案しないでください。
_START TRANSACTION
_およびCOMMIT
を使用してMySQLトランザクションを使用することにより、このプロセスの速度を改善しようとしました。パフォーマンスの向上は驚くべきものでした。処理時間は20分の1に短縮されました。したがって、20分の処理には約1分しかかかりませんでした。
質問。
1.)なぜパフォーマンスが向上したのか(20分から1分)誰もが理解していますか?
2.)100,000件のレコードでトランザクションがどれくらい大きくなるか心配する必要がありますか?
3.)トランザクションでの多数の挿入や更新を心配する必要がありますか?
_/*
* Customer Notes Data:
* Rows are either a meeting, call or note!
*/
$row = 1;
$data = array();
$fields = array();
$line = '';
$db->query('SET autocommit=0;');
$db->query('START TRANSACTION;');
if (($handle = fopen("modules/".$currentModule."/Data/customernote.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 4096, ',', '"')) !== FALSE && $row < 999000) {
//Row 1 - CSV header row with field names
if ($row == 1) {
$csv_fields = $data;
} elseif ($row > 1) {
$fields = $this->process_note_data($data, $csv_fields, $row);
}
$row++;
} // end while
fclose($handle);
}
$db->query('COMMIT;');
$db->query('SET autocommit=1;');
_
注:テキスト/フィールド処理は、$this->process_note_data()
の呼び出しで行われ、INSERT
ステートメントコードを持つ別のヘルパークラスを呼び出します。すべてのコードを含めるのに十分なスペースがありませんでした。 $db->query()
は、MySQLクエリの典型的なデータベースオブジェクトです。
このリンクを確認してください:
https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-transaction-management.html
InnoDBは、トランザクションがデータベースに変更を加えた場合、トランザクションがコミットされるたびにログをディスクにフラッシュする必要があります。各変更の後にコミットが続く場合(デフォルトの自動コミット設定と同様)、ストレージデバイスのI/Oスループットは、1秒あたりの潜在的な操作の数に上限を設けます。
大きなトランザクションは、コミット中のパフォーマンスに影響を与える可能性があります(上記を確認)
ロールバックの場合のみ、ただし、いくつかの設定を使用して最適化できます(リンクを確認してください)
.Netでの私自身の小さなテスト(レコード4フィールド):
INSERT 1レコード、トランザクションなし:6 ms
トランザクションを使用して1レコードを挿入:158 ms
トランザクションを使用して200レコードを挿入し、各レコードの後にコミットします:17778 ms
トランザクションを使用せずに200レコードを挿入します:494 ms
トランザクションを使用して200レコードを挿入し、最後のレコードの後にのみコミットします:4552 ms
トランザクションを使用して1000レコードを挿入し、最後のレコードの後にのみコミットします:21795 ms
デンマークのクライアント、ベルギーのサーバー(Googleクラウドf1-micro)。
これをコメントに入れようとしましたが、フォーマットは良くありません。