Laravel 9+中firstOrCreate()与先查后创建哪个性能更优?
Laravel 9+ 处理40万条记录时,两种方案的性能对比
在Laravel 9+环境下处理约40万条记录时,以下两种实现方式哪种性能更优?我猜测第二种方案性能更好,是否正确?
第一种方案:使用firstOrCreate
$saleId = SaleNumber::firstOrCreate([ 'sale_number' => $line[10], 'sale_date' => $saleDate->format('Y-m-d') ])->id;
第二种方案:手动查询+创建
$saleDate = $saleDate->format('Y-m-d'); $saleNumber = SaleNumber::where('sale_number', $line[10]) ->where('sale_date', $saleDate) ->select('id') ->first(); if(!$saleNumber) { $saleNumber = new SaleNumber(); $saleNumber->sale_number = $line[10]; $saleNumber->sale_date = $saleDate; $saleNumber->save(); } $saleId = $saleNumber->id;
我查看了firstOrCreate的源码实现:
public function firstOrCreate(array $attributes = [], array $values = []) { if (! is_null($instance = $this->where($attributes)->first())) { return $instance; } return tap($this->newModelInstance(array_merge($attributes, $values)), function ($instance) { $instance->save(); }); }
结论:第二种方案性能更优,你的猜测是正确的
核心差异点如下:
- 查询字段更精简:第二种方案通过
select('id')仅查询需要的id字段,而firstOrCreate中的first()会返回模型的所有字段。处理几十万条记录时,减少的数据传输量和模型实例化开销会累积成明显的性能优势。 - 减少不必要的操作:
firstOrCreate内部会执行array_merge($attributes, $values)操作(即便你没传$values参数),而手动创建模型时直接赋值,避免了这一步额外的数组处理开销。
额外注意
无论采用哪种方案,必须给sale_number和sale_date建立联合索引——这是批量处理40万条记录的性能基础。没有索引的话,两种方案都会因为频繁的全表查询变得异常缓慢,性能差异也无从谈起。
内容的提问来源于stack exchange,提问作者Paloma Martinez
相关产品推荐
相关产品推荐

