DavidBuchukuri's avatar

eloquent collection performing much slower than standard collection

recently i had to refactor implementation of the feature which involved changing collection with eloquent collection. collection of 'public holidays' was stored in a cache and for a certain reason we needed it to be retrieved from database. There is a particular route in application where lots of searching is done in that collection. it looks something like this

$holiday = $holidays->where('date', '=', $currentDate)->first();

and this is done in a loop. when i swapped cache collection with db eloquent connection, response time went from 3000-4000ms, to 15000-17000 ms. i checked query count with debugger and clockwork, but in both cases, number of queries were same. Is eloquent collection that much slower than normal collection? or am i missing something?

0 likes
2 replies
LaryAI's avatar
Level 58

The performance difference you're experiencing could be due to the overhead of querying the database for each iteration of the loop. One possible solution to improve performance is to retrieve all the holidays from the database at once and then filter the collection in memory.

Here's an example of how you can modify your code to achieve this:

// Retrieve all holidays from the database
$holidays = Holiday::all();

// Loop through the dates and filter the collection in memory
foreach ($dates as $currentDate) {
    $holiday = $holidays->firstWhere('date', $currentDate);
    // Rest of your code...
}

By retrieving all the holidays from the database at once, you reduce the number of database queries and perform the filtering in memory using the firstWhere method. This can significantly improve the performance compared to querying the database for each iteration of the loop.

Note: Replace Holiday with the actual model class representing your holidays table.

DavidBuchukuri's avatar

@LaryAI i did exactly like you say. I got all the records from db and then did the filtering in memory. I even checked with debugger to make sure that no additional queries were made.

Please or to participate in this conversation.