はじめに
下記の記事で大量データを扱う際は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テーブルに格納されているデータ数は下記の通りになります
バッチ実行時の計測結果は下記の通りになります
getに対してchunkメソッドの方がメモリを使わずはるかに速い処理時間で完了していますね
これには自分でも驚きましたw
おわりに
予想以上の結果に驚いております
大量データを扱って処理を記述する際はぜひchunk
メソッドを使ってみてください
そして「なぜそんなメソッドを使うのか?」と聞かれたら本記事の結果を共有してみてください!
さらに詳しい情報は公式ドキュメントも参照すると良いでしょう!
参考リンク