🙄

CSVインポートを高速化

2024/04/02に公開

CSVインポート時にさまざまな弊害が発生するので、対処法をまとめてみた

ジョブ化する

ファイルを分割して処理できるジョブを作成して分散処理する仕組みに変える。
https://readouble.com/laravel/10.x/ja/queues.html

バッチ処理にする

これができたら苦労しないですが、ユーザー側が操作する時間帯などを避けて自動でデータをインポートするバッチ処理を作成する
https://readouble.com/laravel/10.x/ja/scheduling.html

同時に処理できる件数を減らす

同時にインポートできる件数を1,000件ずつなどにする

バルクインサートを使う

通常SQLは1,000件ずつデータを入れるのが高速になると言われている

$data = [];

$contentIndex = 0;
foreach (range(1, 1000) as $sceneIndex) {
    foreach (range(1, 15) as $index) {
        $contentIndex++;
        $data[] = [
            'id' => $contentIndex,
            'scene_id' => $sceneIndex,
        ];
        if (count($data) >= 1000) {
            DB::table('contents')->insert($data);
            $data = [];
        }
    }
    if (!empty($data)) {
        DB::table('contents')->insert($data);
    }
}

インポート時に行う処理を減らす

計算処理や、別テーブルに移す処理は一旦保留にして、CSVをテーブル化することに集中する

テーブルに同期ではなく、インサート型にする

データをまるっと置き換えるとデータが増えるとインポートするデータも増えてしまう。
保持するデータが増えるのであれば最初からインサートで考えるべき

バリデーションを最低限にする

存在するIDかどうかとか、データチェックに時間がかかってしまう場合もあるので、入力件数を下げることができない場合、バリデーションを減らしてみるのも手の一つ。

Nginxやphp-fpm、phpの設定を見直す

デフォルトのままだとインスタンスのCPUを使い切れていない場合がある、メモリ利用量を増やして、CPUの使用率を上げることもできる

インフラ改善

CPU使用率や、メモリ使用率、ストレージ残量などを見て上記でどうしても改善見込めない場合、スケールアップ/アウトをする

Discussion