大批量假数据填充的正确方法

说明

开发 数据填充 时,必须 特别注意 php artisan db:seed 的运行效率,否则随着项目的代码量越来越大,db:seed 的运行时间会变得越来越长,有些项目多达几分钟甚至几十分钟。

只有当 db:seed 运行起来很快的时候,才能完全利用数据填充工具带来的便利,而不是最后变成累赘。

模型工厂

Laravel 的官方文档中,建议 使用模型工厂来填充数据 ,在日常使用中,需要注意以下。

避免使用 create 方法

在使用 模型工厂函数 来书写假数据插入逻辑时,要注意避免使用 create 方法,因为每一次就是一条 SQL 语句。

factory(\App\Models\User::class)->times(300)->create();

以下截图是一个使用 factory 辅助函数的例子,插入 300 条数据,总共执行了 602 条 SQL 语句,总执行时长为 23.91 秒。

file

轻轻松松运行时间就累积起来了,你能想象运行一次 db:seed 要半个小时是什么感觉么?

c4o3E6gq7W.png

正确的做法:使用 make 方法

$users = factory(\App\Models\User::class)->times(1000)->make();
\App\Models\User::insert($users->toArray());

file

感谢 @NauxLiu :smile: :sparkles: :sparkles:

传统方式

一个错误的例子

下面代码执行了 1000 条 SQL 语句,在书写数据填充的时候,也是要尽量避免。

$faker = Faker::create();
$users = User::lists('id');

foreach (range(1, 1000) as $index)
{
    Topic::create([
        'user_id'     => $faker->randomElement($users),
        'title'       => $faker->sentence(),
        'description' => $faker->text(),
    ]);
}

解决方案

使用 DB:insert,直接,快速,一步到位:

$faker = Faker::create();
$users = User::lists('id');
$datas = [];

foreach (range(1, 1000) as $index)
{
  $datas[] = [
      'user_id'     => $faker->randomElement($users),
      'title'       => $faker->sentence(),
      'description' => $faker->text(),
      'created_at'  => Carbon::now()->toDateTimeString(),
      'updated_at'  => Carbon::now()->toDateTimeString(),
  ];
}
DB::table('topics')->insert($datas);

只有 db:seed 运行起来很快的时候,你才可以随时随地,想 seed 就 seed。

--- EOF ---


Practice makes perfect.

本帖已被设为精华帖!
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 14
Summer

@NauxLiu 贴代码

3年前
Summer

@NauxLiu 发哥说你家猫很吵

3年前
Summer

@NauxLiu 估计是猫被「死亡呼噜」吵到有点焦躁了。

3年前
Complicated

楼主我有个疑问,我之前都是先定义好了在factory.php,然后用命令行执行 factory(。。。,1000)->create(),确实挺慢的。你说这种先make(),再转成数组,再插入挺好,但是是分好几步的啊,用命令行怎么完成?第一次make()了之后,数据就打印到了额控制台,还怎么再toArray啊?小弟新学,见笑了

1年前

请问,如果要插入的数据的同时也要插入关联表的数据,用insert还好弄吗?

1年前

发现了一个秘密,文章的阅读数量是以2为基数递增的,别问我怎么知道的(现在是凌晨2:35)

1年前

@vidon520 貌似create的时候会忽略$fillable和$hidden,但是make不会忽略.所以被hidden的字段就会为空...不知道最新版本的laravel有没有对create进行优化...

1年前

@刘拯明 5.6的也还是存在这种情况呢

10个月前

修改 ModelFactory.php 文件后每次都要执行 composer dump-autoload 吗?
头几次执行没问题 但是后面执行就报错
file

删除vendor文件后执行 composer install 可以执行 但是再次执行 composer dump-autoload 还是报错 这到底是为什么呢? 有遇到过这个问题的吗?

9个月前

文中执行语句数量,时间,使用什么查看的

9个月前

大批量假数据填充的时候,可以考虑下用存储过程,效率绝对杠杠的 :see_no_evil:

9个月前

填充时如果碰到有模型访问器的时候会出现生成的假数据经过访问器

1个月前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

社区文档:

将托管在 packagist.org 和 github.com 的扩展包使用国内 CDN 加速
GitHub Laravel 扩展包 TOP 250
速查表方便快速查询框架功能,支持手机访问,支持中英文版本
Laravel 中文文档,由社区用户翻译和维护,将会保持一直更新
此文档的目的,就是为了提高技术团队的凝聚力、一致性和生产效率。
开发环境的部署,开发者工具的选择,适用于 Mac 和 Windows。
浓缩过后的精华
Laravel Nova 后台管理面板文档的中文翻译
Lumen 中文文档,由社区用户翻译和维护,将会保持一直更新
Laravel 下知名扩展包 Dingo API 的中文文档,Laravel API 开发必知必会