【问题标题】:Fastest way to insert data in Laravel [duplicate]在 Laravel 中插入数据的最快方法 [重复]
【发布时间】:2020-02-28 11:28:12
【问题描述】:

我制作了一种复制分支用户权限的方法。权限通常为 0 到 120 个项目。运行此方法将这个(0 到 120)项插入到 7 个 user_ids 需要 35-55 秒才能插入到表中。

/**
 * Copy Branch User Permissions
 *
 * @param Int
 * @param Int
 * @param Int
 * @return Array
 */
public function copyBranchUserPermissions($branchIdFrom, $branchIdTo, $userId)
{
    $permissions = BranchPermissionUser::get()
        ->where('branch_id', $branchIdFrom)
        ->where('user_id', $userId);

    foreach($permissions as $permission) {
        $permission->create([
            'branch_id' => $branchIdTo,
            'permission_id' => $permission->permission_id,
            'user_id' => $userId
        ]);
    }

    return $permissions;
}

我需要优化这个过程,因为插入数据的性能很慢。我在想如果超过 10 个用户怎么办,所以这个过程会花费太长时间。有什么办法可以提高插入数据的性能速度?

提前谢谢你!

【问题讨论】:

标签: php sql laravel optimization


【解决方案1】:

你可以使用 Eloquent insert() 方法。

public function copyBranchUserPermissions($branchIdFrom, $branchIdTo, $userId)
{
    $permissions = BranchPermissionUser::where('branch_id', $branchIdFrom)
                    ->where('user_id', $userId)
                    ->get();

    $data=[];
    foreach($permissions as $permission) {
      $data[] = [
        'branch_id' => $branchIdTo,
        'permission_id' => $permission->permission_id,
        'user_id' => $userId
      ];
    }
    BranchPermissionUser::insert($data);
    return $permissions;
}

【讨论】:

    【解决方案2】:

    您可以使用 Eloquent fill() 方法。

    public function copyBranchUserPermissions($branchIdFrom, $branchIdTo, $userId)
    {
        $permissions = BranchPermissionUser::where('branch_id', $branchIdFrom)
                        ->where('user_id', $userId)
                        ->get();
    
        foreach($permissions as $permission) {
          $permission->fill([
            'branch_id' => $branchIdTo,
            'permission_id' => $permission->permission_id,
            'user_id' => $userId
          ]);
           $permission->save();
        }
        return $permissions;
    }
    

    这将帮助您提高函数的速度,因为您正在循环的是您从查询中获得的结果,而不是查询本身的结果。为了使用fill() 函数,您的数据类型必须是fillable

    【讨论】:

      【解决方案3】:

      如果您非常需要速度优化,最好坚持使用查询生成器,而不是采用 Eloquent 方式。

      更多信息: Laravel Eloquent vs query builder - Why use eloquent to decrease performance

      当您获取用户和特定于分支的权限时

       $permissions = BranchPermissionUser::get()
          ->where('branch_id', $branchIdFrom)
          ->where('user_id', $userId);
      

      您首先从数据库表中加载所有数据,并对所有数据生成的集合执行 where。

      您应该在 get 方法之前执行 where 条件,因此它将在 SQL 端进行处理,这将比在从 get eloquent 方法创建的集合中进行处理要快得多。

      $permissions = BranchPermissionUser::query()
                              ->where('branch_id', $branchIdFrom)
                              ->where('user_id', $userId)
                              ->get();
      

      此外,您正在循环访问所有权限并在数据库中创建每个权限。

       foreach($permissions as $permission) {
          $permission->create([
              'branch_id' => $branchIdTo,
              'permission_id' => $permission->permission_id,
              'user_id' => $userId
          ]);
      

      这将为每个创建创建一个查询。这非常慢,而且不是同时保存多行数据的最佳做法。

      您应该使用insert 方法插入所有行,这会创建一个单一的 SQL 查询,并且速度更快且优化。

      注意:插入行时,Insert 方法不会处理 created_at 和 updated_at 字段。所以你必须手动为它们添加数据。

      $data=[];
      foreach($permissions as $permission) {
        $data[] = [
          'branch_id' => $branchIdTo,
          'user_id' => $userId,
          'permission_id' => $permission->permission_id,
          'created_at' => now(),
          'updated_at' => now(),
        ];
      }
      BranchPermissionUser::insert($data);
      

      now() 是一个 Laravel 助手,它为当前时间创建一个新的 Carbon 实例:。

      【讨论】:

        猜你喜欢
        • 2017-03-26
        • 2014-03-08
        • 2013-04-11
        • 1970-01-01
        • 2021-10-30
        • 1970-01-01
        • 2014-09-12
        • 2016-08-12
        • 1970-01-01
        相关资源
        最近更新 更多