Which performs better: eloquent or DB query builder?

Have you ever considered which is more powerful: eloquent or DB query builder? I had this question in my head for a while, so in this article, we are going to answer it.

|
5 min read
|
blog-post-hero

Do you need to work with eloquent in your next project or DB query builder? or maybe combine them. I mean have you ever thought that working with these tools may have an impact on performance? for me I never did and I hope I'm not the only one 😝, and there's a good chance you didn't either, or you wouldn't be reading this xD.

Comparison will be straightforward: I'll start a Laravel project and install the Laravel Debugbar, then we'll generate fake data and compare memory usage and execution time.

Project setup

The easiest way to create a project is to use composer

CMD
composer create-project laravel/laravel example-app

then install Laravel Debugbar package and publish it by running:

CMD
composer require barryvdh/laravel-debugbar --dev

// Publish Debug Bar
php artisan vendor:publish --provider="Barryvdh\Debugbar\ServiceProvider"

Now restart the server and clear caches

CMD
composer dump-autoload

php artisan optimize

make sure that you have APP_DEBUG set to true in .env

.env
APP_DEBUG=true

Now, if you visit the welcome page, you should see the debugging bar

project-setup

Creating fake data

The first thing I'm going to test is retrieving the users from the database, then I'm going to create a hobby model in order to also test the performance in case of relationships, Laravel comes with a User model so we don't need to create it, but we do need to create the Hobby model, migration and factory.

CMD
php artisan make:model Hobby -mf

The Hobbies table will be simple, I will create two fields, the first for the name of the hobby and the second is a foreign key of the users table.

create_hobbies_table.php
class CreateHobbiesTable extends Migration
{
    public function up()
    {
        Schema::create('hobbies', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->foreignIdFor(User::class);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('hobbies');
    }
}

next let's define the relationship on User's model and update HobbyFactory

User.php
public function hobbies()
{
   return $this->hasMany(Hobby::class);
}
HobbyFactory.php
class HobbyFactory extends Factory
{
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
        ];
    }
}

and finally we can seed the data

DatabaseSeeder.php
class DatabaseSeeder extends Seeder
{
    public function run()
    {
        User::factory(5000)
            ->has(Hobby::factory()->count(2))
            ->create();
    }
}

Testing Executing time and memory usage

So, now we've

  • 10,000 hobbies
  • 5,000 users

I created a controller to test my queries, you can see below the two ways to retrieve all user records, the first syntax is for eloquent and the second is DB query builder.

UsersController.php
public function index()
{
    $users = User::all();
    // $users = DB::table('users')->get();

    return view('welcome', compact('users'));
}

after the execution I found the following results:

Eloquent / DB query builderDebugbar metrics
eloquenteloquent_retrieving_all_records
DB query Builderdb_query_builder_retrieving_all_records

So, to retrieve 5k users with eloquent, we consumed 13MB of memory and it took 154ms, on the other hand, it only takes 9MB of memory and 86ms using DB query builder.

What about a simple join?

let's retrieve the first user with his hobbies:

UsersController.php
// eloquent
$users = User::query()
    ->whereKey(1)
    ->with('hobbies')
    ->get();

// DB query Builder
$users = DB::table('users')
    ->select('users.name', 'hobbies.name')
    ->join('hobbies', 'hobbies.user_id', '=', 'users.id')
    ->where('users.id', 1)
    ->get();    

after the execution I found the following results:

Eloquent / DB query builderDebugbar metrics
eloquenteloquent_joins
DB query Builderdb_query_builder_joins

So, we consumed 5MB of memory and it took 61.87ms, and only 4MB of memory and 86ms using DB query builder.

Results and final thoughts

Clearly DB query builder was performing slightly better than Eloquent query builder, so does this means that from now you should start only using DB query builder? absolutely not I will summarize my point of view in the table below:

Eloquent Query BuilderDB Query Builder
Eloquent Query Builder takes more memory and timeDB Query Builder takes less memory and time
Performance lower for big dataPerformance higher for big data
Code is friendly and readableSQL becomes more complex and unreadable
Not recommended where working with multiple joinsGreat for many joins

So, it depend on your project size and perspective. usually I work with them both and in case of joins I use DB query builder for the optimal performance.

#Laravel
Share