I recently worked on a project where I had to insert a lot of dummy data into a database for testing. Laravel provides a feature called seeding just for this purpose. Seeding can take much time if you are trying to insert many records. In my case, I was trying to seed 100k users into my User model database, and it was taking a long time. However, by doing some optimization, I was able to bring down the execution time from ~75 seconds to around ~30 seconds!. So, let me show you how to quickly seed 100k records in Laravel.

What is Database Seeding?

Database Seeding is a process wherein you insert dummy data into your database tables to test your application. Seeding is helpful if you want to test functionality such as pagination, table load time, and the application responsiveness under full load. With seeding, you can mimic how your application would behave once it is in production and has to handle large amounts of data.

Setting Up a New Laravel Project

We’ll begin by setting up a new Laravel project and a users table. Laravel comes with a default user model out of the box and we’ll use this as an example to demonstrate database seeding. Regardless of the model, the seeding process will be the same and can be adapted to any model.

Without further ado, let’s create a new Laravel project with composer:

composer create-project --prefer-dist laravel/laravel 100k-records-seed-laravel

After that, set the database details in the .env file. This file is a centralized repository for all the configurations related to Laravel.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-seed
DB_USERNAME=root
DB_PASSWORD=

I have created a MySQL database named laravel-seed and set it here. However, I will not be covering that here for the sake of brevity.

Subsequently, run the default migrations to create the user related tables.

php artisan migrate

Creating Seeder for Users Table

Let’s get started with seeding. To create a Seeder class for eloquent models, we need to use the make:seeder command provided by artisan. We’ll generate one for our user model:

php artisan make:seeder UserSeeder

After that, you will find that a UserSeeder.php file is created in the database/seeds directory. We’ll add our seeding logic to the run() method in this class, which will be done in the next section of this tutorial.

Meawhile, we’ll call the Seeder class from the DatabaseSeeder.php file. Laravel invokes DatabaseSeeder to execute seeders. Therefore, we need to add any and all the seeders we have to this file.

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UserSeeder::class);
    }
}

Seeding 100,000 Records for User Model

I set up my project in an AWS EC2 environment to make the seeding as fast as possible. To insert 100,000 rows in the database, I used a simple for loop that runs 100k times and adds randomly generated details into the user model.

<?php

use Illuminate\Database\Seeder;
use App\User;


class UserSeeder extends Seeder
{

    private $userData = [];

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {

        for ($i=0; $i < 100000; $i++) {
            $userData[] = [
                'name' => Str::random(10),
                'email' => Str::random(10).'@gmail.com',
                'password' => Hash::make('password')
            ];
        }

        foreach ($userData as $user) {
            User::create($user);
        }
    }
}

Although the above code gets the job done, it is not very efficient and I’ll explain some optimization methods later in this post. Now, let’s add the UserSeeder class to the DatabaseSeeder.php file.

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UserSeeder::class);
    }
}

Next, re-generate composer’s autoload file using the dump-autoload command.

composer dump-autoload

Now let’s run the DatabaseSeeder using artisan’s db:seed command. This command executes the DatabaseSeeder class which in turn calls all other seeder classes.

php artisan db:seed

As I explained earlier, the code is not efficient so the seeding process takes quite some time. In my case, it took about 75.82 seconds.

C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel> php artisan db:seed
Seeding: UserSeeder
Seeded:  UserSeeder (75.82 seconds)
Database seeding completed successfully.
C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel>

In the next section, we’ll look at some ways to optimize database seeding.

Ways to Optimize Database Seeding

1. Use Insert() instead of Create()

The first thing that we can do to improve our code is to use User::insert() instead of User::create(). If you check the Laravel Eloquent documentation, create() does many things under the hood, such as checking the $fillable variable and populating timestamps. Also, create inserts only one record at a time, which is not a good query implementation.

On the other hand, insert() does not do any of that; it just translates our data into SQL query and runs it. Hence, it is much faster than using create().

<?php

use Illuminate\Database\Seeder;
use App\User;


class UserSeeder extends Seeder
{

    private $userData = [];

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {

        for ($i=0; $i < 100000; $i++) {
            $userData[] = [
                'name' => Str::random(10),
                'email' => Str::random(10).'@gmail.com',
                'password' => Hash::make('password'),
                'created_at' => now()->toDateTimeString(),
                'updated_at' => now()->toDateTimeString(),
            ];
        }

        foreach ($userData as $user) {
            User::insert($user);
        }
    }
}

So, let’s reset our database and run the db:seed command once again.

php artisan migrate:fresh
php artisan db:seed
C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel> php artisan db:seed
Seeding: UserSeeder
Seeded:  UserSeeder (66.15 seconds)
Database seeding completed successfully.
C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel>

As you can see, the execution time was reduced by 20% which is a considerable improvement for a small modification that we made.

2. Array Chunking

We can optimize our code even further by using chunking. Chunking is the process of dividing a large array into smaller sub-arrays. Therefore, instead of inserting just one record at a time, we can directly insert these chunks into our database.

We use PHP’s array_chunk to divide our array and insert them at once into the database, like so:

<?php

use Illuminate\Database\Seeder;
use App\User;


class UserSeeder extends Seeder
{

    private $userData = [];

    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {

        for ($i=0; $i < 100000; $i++) {
            $userData[] = [
                'name' => Str::random(10),
                'email' => Str::random(10).'@gmail.com',
                'password' => Hash::make('password'),
                'created_at' => now()->toDateTimeString(),
                'updated_at' => now()->toDateTimeString(),
            ];
        }


        $chunks = array_chunk($userData, 5000);

        foreach ($chunks as $chunk) {
            User::insert($chunk);
        }
    }
}

Finally, lets clear our database again, and re-run the seeder.

php artisan migrate:fresh
php artisan db:seed
C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel> php artisan db:seed
Seeding: UserSeeder
Seeded:  UserSeeder (38.46 seconds)
Database seeding completed successfully.
C:\Users\sapneshn\Documents\Hobby\codezen\100k-records-seed-laravel>

Once again, the execution time has been reduced further, this time by 50%.

Wrapping Up

That’s how you can seed a lot of database records at once in Laravel. Seeding is helpful for testing your application, checking for bugs, and monitoring your application performance under heavy load.

If you have any other ways to speed up the seeding process, please share your tips in the comments below.