🐈
[Laravel]Collection::whereBetweenが遅い
はじめに
LaravelのCollection::whereBetween()
からのCollection::count()
が遅かったので、配列で処理した時との速度比較をしてみました。
動作環境
PHP 8.1.29
Laravel Framework 10.32.1
検証コード
private function countRange($nums, $from, $to) {
$count = 0;
foreach ($nums as $num) {
if ($num >= $from && $num <= $to) {
$count++;
}
}
return $count;
}
public function run() {
$COUNT = 1000;
$BETWEEN_FROM = 0.3 * $COUNT;
$BETWEEN_TO = 0.5 * $COUNT;
// Collection作成
$items = collect()->range(0, $COUNT)
->map(function ($index) use ($COUNT) {
return [
'id' => $index,
'number' => random_int(0, $COUNT),
];
});
$collectionTotal = 0;
$arrayTotal = 0;
// 計測
for ($i = 0; $i < 10; $i++) {
// Collectionのまま処理
$start = microtime(true);
$items->whereBetween('number', [$BETWEEN_FROM, $BETWEEN_TO])->count();
$collectionTotal += microtime(true) - $start;
// 配列に変換してから処理
$start = microtime(true);
$numbers = $items->map(fn($item) => $item['number'])->toArray();
$this->countRange($numbers, $BETWEEN_FROM, $BETWEEN_TO);
$arrayTotal += microtime(true) - $start;
}
// 10回計測の平均値を出力する。
var_dump("Collection:" . $collectionTotal / 10);
var_dump("Array:" . $arrayTotal / 10);
}
検証結果
要素数 | Collection | Array |
---|---|---|
1,000件 | 0.00550秒 | 0.00059秒 |
10,000件 | 0.05393秒 | 0.00574秒 |
100,000件 | 0.52312秒 | 0.06067秒 |
1,000,000件 | 5.35373秒 | 0.66113秒 |
10,000,000件 | 61.88503秒 | 7.02155秒 |
大体9倍近くの差が出ました。
今回のケースはBetweenで絞った結果の件数を取得する処理でしたが、
他にもCollectionで処理する必要がない場合は、配列に変換してから処理した方が速度は有利ですね。
Discussion