美文网首页
Laravel 如何生成一千万条数据表记录

Laravel 如何生成一千万条数据表记录

作者: zshanjun | 来源:发表于2017-03-07 15:03 被阅读992次

    Laravel 批量填充数据流程

    一般我们使用laravel填充数据,一般按照下面的流程:

    1、使用model factory定义要填充的数据结果
    2、在DatabaseSeeder.php里面进行调用填充

    示例:

    //model factory
    
    $factory->define(NewProduct::class, function (Faker\Generator $faker) {
        $fabrication_ids = Fabrication::lists('id')->toArray();
        $fabric_width_ids = FabricWidth::lists('id')->toArray();
        $fabric_weight_ids = FabricWeight::lists('id')->toArray();
        $gauge_ids = Gauge::lists('id')->toArray();
        $diameter_ids = Diameter::lists('id')->toArray();
        $production_property_ids = ProductionProperty::lists('id')->toArray();
        $content_ids = Content::lists('id')->toArray();
        $creator_ids = Account::lists('FID')->toArray();
    
        return [
            'code'                    => $faker->word,
            'name'                    => $faker->word,
            'name_en'                 => $faker->word,
            'fabrication_id'          => $faker->randomElement($fabrication_ids),
            'fabric_width_id'         => $faker->randomElement($fabric_width_ids),
            'fabric_weight_id'        => $faker->randomElement($fabric_weight_ids),
            'gauge_id'                => $faker->randomElement($gauge_ids),
            'diameter_id'             => $faker->randomElement($diameter_ids),
            'production_property_id'  => $faker->randomElement($production_property_ids),
            'content_id'              => $faker->randomElement($content_ids),
            'creator_id'              => $faker->randomElement($creator_ids),
            'remark'                  => $faker->text(200),
        ];
    });
    
    
    //DatabaseSeeder.php
    
    factory(NewProduct::class, 1000)->create();
    
    
    

    以上代码,存在一个很严重的问题,create()方法会每创建一条记录都执行一条sql语句。脚本运行大概需要40s。

    Laravel 优化批量填充数据

    1、新建一个批量填充的文件,这里以NewProductSeeder.php为例
    2、在DatabaseSeeder.php里进行调用

    示例:

    //NewProductSeeder.php
    
    //获取相关联属性的值,为防止数据过多,限制每次只取10000条
    //为加快获取数据速度,在有索引的id列上进行排序
    $fabrication_ids = Fabrication::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $fabric_width_ids = FabricWidth::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $fabric_weight_ids = FabricWeight::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $gauge_ids = Gauge::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $diameter_ids = Diameter::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $production_property_ids = ProductionProperty::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $content_ids = Content::orderBy('id', 'desc')->take(10000)->lists('id')->toArray();
    $creator_ids = Account::lists('FID')->toArray();
    //利用两层循环,脚本每次运行总共生成20000条记录
    //利用一个临时数组来批量保存临时数据
    //数组不宜设置过大,否则会导致异常
    foreach (range(0, 10) as $index) {
        $products = [];
        $date = $faker->dateTime;
        foreach (range(0, 2000) as $index) {
            $products[] = [
                'code'                   => $faker->word,
                'name'                   => $faker->word,
                'name_en'                => $faker->word,
                'fabrication_id'         => $faker->randomElement($fabrication_ids),
                'fabric_width_id'        => $faker->randomElement($fabric_width_ids),
                'fabric_weight_id'       => $faker->randomElement($fabric_weight_ids),
                'gauge_id'               => $faker->randomElement($gauge_ids),
                'diameter_id'            => $faker->randomElement($diameter_ids),
                'production_property_id' => $faker->randomElement($production_property_ids),
                'content_id'             => $faker->randomElement($content_ids),
                'creator_id'             => $faker->randomElement($creator_ids),
                'remark'                 => $faker->text(200),
                'created_at'             => $date,
                'updated_at'             => $date
            ];
        }
        NewProduct::insert($products);
    }
    
    
    
    //DatabaseSeeder.php
    
    $this->call(NewProductSeeder::class);
    
    
    

    填充一千万条记录

    利用上面的脚本,只需要结合linux里面的cron job即可很简单的实现填充一千万条记录的目标

    1、添加任务

    在app/Console/Kernel.php文件里面添加上任务:

        protected function schedule(Schedule $schedule)
        {
            $schedule->exec('php artisan db:seed')
                     ->everyMinute()
                     ->withoutOverlapping();
        }
    

    2、添加crontab任务

    在linux里面输入crontab -e打开crontab文件,添加下面代码,保存退出即可运行代码:

    * * * * * php /home/vagrant/Code/sfabric/artisan schedule:run >> /dev/null 2>&1
    
    

    3、坐等成功

    按照上面的填充速度(一分钟填充4w条记录),需要250分钟即可。

    注意,实际使用时请根据上面脚本的执行速度,来动态调整每分钟生成的记录条数(调整最外层range即可)

    (这个例子中,实际代码涉及到更多插入,4w条主表记录加8w条关联表记录加3.5k条其它属性记录,只需要50s)

    tips:为加快速度,可在批量添加时,提前删除索引,添加完成后再添加索引。


    参考网站:

    相关文章

      网友评论

          本文标题:Laravel 如何生成一千万条数据表记录

          本文链接:https://www.haomeiwen.com/subject/equmgttx.html