$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[September 15, 2025] Eloquent ORM

Eloquent Bulk Insert: Performance

Eloquent Bulk Insert: Performance

────────────────────────────────────────────────────────

Eloquent Bulk Insert: Performance

Tip: insert() for Bulk

DB::table('posts')->insert([
    ['title' => 'A', 'slug' => 'a'],
    ['title' => 'B', 'slug' => 'b'],
]);

Gotcha: No Events or Timestamps

DB::table()->insert() doesn't fire events or set timestamps.

Tip: insertOrIgnore()

DB::table('posts')->insertOrIgnore([
    ['slug' => 'a', 'title' => 'A'],
]);

Skips duplicates without error.

Gotcha: Chunk Large Inserts

collect($data)->chunk(1000)->each(fn($chunk) => DB::table('posts')->insert($chunk->toArray()));

Tip: upsert() for Insert or Update

Post::upsert($data, uniqueBy: ['slug'], update: ['title']);

Gotcha: Model create() in Loop

foreach ($data as $item) {
    Post::create($item); // Slow - one query per iteration
}

Tip: Use cursor() for Memory-Neutral Iteration

When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.

Tip: whereHas() vs load() — Two Different Things

whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.

Gotcha: withCount() Adds a Subquery

withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.

Senior Insight

Bulk inserts with insert() are much faster than individual create() calls, but they bypass model events and attribute casting. I've seen teams use insert() for performance and then wonder why JSON columns weren't cast to arrays. For large bulk inserts where casting matters, I pre-process the data array through the model's castAttribute() method before calling insert(). And I never use insert() when I need event handling — use chunk() + create() instead.

Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)

────────────────────────────────────────────────────────
<-- back to posts