0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Eloquentのgetメソッドとchunkメソッドのパフォーマンスを比較してみる

Last updated at Posted at 2024-06-29

はじめに

下記の記事で大量データを扱う際はchunkメソッドを使った方が良いといった内容を書きましたが、実際にどれくらい良くなるかを今回は検証してみました

パフォーマンステストの準備

  • データベースの準備
    • テスト用のデータベースを用意し、十分なレコード数を挿入します
    • 今回は4000件のデータを使用します
  • 環境の準備
    • 同じ環境でテストを行います
    • 今回はDocker+Laravel+MySQLの環境で行います
    • 詳しくは下記の記事をご参照ください

測定項目

  • メモリ使用量
    • 各メソッド使用時のメモリ消費量を測定します
  • 処理時間
    • 各メソッドが処理を完了するまでの時間を測定します

テストデータの使用

テストデータは下記を使用しました

world database

というDBのcityテーブルを使います
後続のモデルを作成をした際に使用するのでテーブル名はcitiesにしておきます

モデルの作成

docker compose exec app php artisan make:model City

モデル名は単数形ですが、参照先のテーブル名は複数形であることを前提としています

バッチでスクリプトを作成

今回はバッチファイルで検証します

  • Laravelのartisanコマンドでバッチを作成
php artisan make:command TestPerformance

これにより、app/Console/Commands/TestPerformance.phpというファイルが作成されます
このファイルを編集します

TestPerformance.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\City;

class TestPerformance extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:test-performance';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->testGetMethod();
        $this->testChunkMethod();
    }

    private function testGetMethod()
    {
        // メモリ使用量の初期値を取得
        $initialMemory = memory_get_usage();

        // 処理開始時間を取得
        $startTime = microtime(true);

        // getメソッドでcityを取得
        $cities = City::get();
        
        foreach ($cities as $city) {
            // ダミー処理
            $uppercaseName = strtoupper($city->name);
            $nameLength = strlen($uppercaseName);
            // ここで、変数 $uppercaseName と $nameLength を使用してダミーの処理を行う
            // 実際には何もしていないが、処理が行われたと仮定する
        }

        $endTime = microtime(true);

        // メモリ使用量の差分を計算
        $memoryUsage = memory_get_usage() - $initialMemory;

        // 処理時間を計算
        $executionTime = $endTime - $startTime;

        $this->info("getメソッドのメモリ使用量:" . $memoryUsage . "bytes");
        $this->info("getメソッドの処理時間: " . $executionTime . " seconds");
    }

    private function testChunkMethod()
    {
        // メモリ使用量の初期値を取得
        $initialMemory = memory_get_usage();

        // 処理開始時間を取得
        $startTime = microtime(true);

        // chunkメソッドでcityを分割して取得
        City::chunk(1000, function($cities) {
            foreach ($cities as $city) {
                // ダミー処理
                $uppercaseName = strtoupper($city->name);
                $nameLength = strlen($uppercaseName);
                // ここで、変数 $uppercaseName と $nameLength を使用してダミーの処理を行う
                // 実際には何もしていないが、処理が行われたと仮定する
            }
        });

        $endTime = microtime(true);

        // メモリ使用量の差分を計算
        $memoryUsage = memory_get_usage() - $initialMemory;

        // 処理時間を計算
        $executionTime = $endTime - $startTime;

        $this->info("chunkメソッドのメモリ使用量: " . $memoryUsage . " bytes");
        $this->info("chunkメソッドの処理時間: " . $executionTime . " seconds");
    }
}

計測結果

まず、citiesテーブルに格納されているデータ数は下記の通りになります

image.png

バッチ実行時の計測結果は下記の通りになります

image.png

getに対してchunkメソッドの方がメモリを使わずはるかに速い処理時間で完了していますね
これには自分でも驚きましたw

おわりに

予想以上の結果に驚いております
大量データを扱って処理を記述する際はぜひchunkメソッドを使ってみてください
そして「なぜそんなメソッドを使うのか?」と聞かれたら本記事の結果を共有してみてください!
さらに詳しい情報は公式ドキュメントも参照すると良いでしょう!

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0