当超过 10k 数据时,Laravel 数据表加载缓慢

Posted

技术标签:

【中文标题】当超过 10k 数据时,Laravel 数据表加载缓慢【英文标题】:Laravel Datatables load slow when more than 10k data 【发布时间】:2021-11-16 12:19:35 【问题描述】:

加载超过 10k 条记录时性能变慢

页面加载时间:8.00 秒

问题: 当数据超过10k时,是否有人必须面临类似的问题,返回数据会很慢?有什么优化的想法吗?当用户访问页面时,即使我已经在表中索引了,也需要将近 8 秒才能加载所有数据。

系统详情

php 7.3, Laravel 8.4, Laravel-Yajra-Datatables v9.18。

代码

控制器

public function getPlayerlistAction(Request $request)
    
        if ($request->ajax()) 

            $player = Player::where('parent_id', Auth::user()->id)
                        ->with(['getGames' => function ($q)
                            $q->select('id', 'title', 'display_name');
                        ])
                        ->orderBy('created_at', 'desc')
                        ->get()
                        ->toArray();

            return Datatables::of($player)
                //->addIndexColumn()
                ->addColumn('games', function ($row) 
                    $data = $row['get_games']['display_name'];
                    return $data;
                )
                ->addColumn('phone_number', function ($row) 
                    $data = "";
                    if($row['phone_number'] == '000')
                        $data = "-";
                    else
                        $data = $row['phone_number'];
                    
                    return $data;
                )
                ->addColumn('balance', function ($row) 
                    $data = number_format($row['balance'], 2);
                    return $data;
                )
                ->addColumn('status', function ($row) 
                    if ($row['status'] == 1) 
                        $actionBtn = '<span class="badge badge-pill badge-success">' . __('mainlanguage.enabledtxt') . '</span>';
                     else if($row['status'] == 0) 
                        $actionBtn = '<span class="badge badge-pill badge-danger">' . __('mainlanguage.disabledtxt') .'</span>';
                    
                    return $actionBtn;
                )
                ->addColumn('action', function ($row) 
                   $actionBtn  = '<span><button class="btn btn-primary btn-sm mt-1 mr-1 setscrore" data-gameusername="' . $row['game_username'] . '" data-game="' . $row['get_games']['title'] . '" data-username="' . $row['player_no'] . '" data-gid="' . $row['games_id'] . '"><i class="fa fa-credit-card"></i> ' . __('mainlanguage.setscoretxt') . '</button>';
                   $actionBtn .= '<button class="btn bg-orange color-palette btn-sm mt-1 mr-1 resetpwd" data-gameusername="' . $row['game_username'] . '"data-gid="' . $row['games_id'] . '"data-username="'.$row['player_no'].'" ><i class="fa fa-unlock"></i> ' . __('mainlanguage.resetpasstxt') . '</button>';
                   if($row['status'] == 1)
                        $actionBtn .= '<button class="btn btn-danger btn-sm mt-1 mr-1 disable" datatype=0 data-gameusername="' . $row['game_username'] . '" data-gid="' . $row['games_id'] . '" data-username="' . $row['player_no'] . '"><i class="fa fa-ban"></i> ' . __('mainlanguage.disabletxt') . '</button>';
                   else
                        $actionBtn .= '<button class="btn btn-success btn-sm mt-1 mr-1 disable" datatype=1 data-gameusername="' . $row['game_username'] . '" data-gid="' . $row['games_id'] . '" data-username="' . $row['player_no'] . '"><i class="fa fa-ban"></i> ' . __('mainlanguage.enabledtxt') . '</button>';
                   
                   $actionBtn .= '<button class="btn bg-teal color-palette btn-sm mt-1 mr-1 gamelog" data-gamename="'.$row['get_games']['title'].'" data-gameusername="' . $row['game_username'] . '" data-gid="' . $row['games_id'] . '" data-username="' . $row['player_no'] .'"><i class="fa fa-scroll"></i> ' . __('mainlanguage.gamelogtxt') . '</button>';
                   $actionBtn .= '<button class="btn bg-maroon color-palette btn-sm mt-1 mr-1 transactionlog" data-gameusername="' . $row['game_username'] . '" data-gid="' . $row['games_id'] . '" data-username="' . $row['player_no'] .'"><i class="fa fa-book"></i> ' . __('mainlanguage.tranactilogtxt') . '</button></span>';
                   return $actionBtn;
                )
                ->rawColumns(['games', 'balance', 'status', 'action', 'phone'])
                ->make(true);
        
    

JS

$('.playertable').DataTable(
            "language": 
                "url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/"+lag
            ,
            processing: true,
            -- serverSide: true,  --
            responsive: true,
            searching:  true,
            "order": [[ 5, "desc" ]],
            ajax: 
                url: " route('getplayerlist') ",
                type: 'GET',
                data: function (d) 
                    -- d.name = $('#name').val();
                    d.email = $('#email').val(); --
                
            ,
            columns: [
                    data: 'games', name: 'games',
                    data: 'player_no', name: 'username',
                    data: 'game_username', name: 'gameid',
                    data: 'balance', name: 'balance',
                    data: 'phone_number', name: 'phone',
                    data: 'created_at', name: 'createdate',
                    data: 'status', name: 'status',
                    data: 'action', name: 'action', orderable: false, searchable: false, 'className': "dt-center",
                ]
        );

【问题讨论】:

enable serverSide: true, in datatable and remove ->get() ->toArray();以便 Laravel-Yajra-Datatables 对查询中的数据进行分页和限制 【参考方案1】:

将您的代码更改为:

$player = Player::where('parent_id', Auth::user()->id)
      ->with(['getGames' => function ($q)
          $q->select('id', 'title', 'display_name');
  ])
  ->orderBy('created_at', 'desc');

  return Datatables::eloquent($player)
  //....

【讨论】:

如果您遇到任何错误,请告诉我 嗨@sta,它返回错误消息:“调用未定义的方法 Illuminate\\Database\\Eloquent\\Builder::query()” 现在再试一次,也取消注释这行serverSide: true, 您好,感谢您的帮助。现在可以工作了。 变成了 1.0 秒。非常快【参考方案2】:

取消注释 serverSide: true

删除这个

->get()->toArray();

并将其替换为:

->latest();

【讨论】:

总是解释你的答案,以便其他人可以从中学习。 您好,感谢您的帮助。现在可以工作了。

以上是关于当超过 10k 数据时,Laravel 数据表加载缓慢的主要内容,如果未能解决你的问题,请参考以下文章

Mule 4:Dataweave 2.0:如何处理大小超过10k的数据库记录?

如何从具有 10k 条记录的 mysql 数据库中快速检索数据

尝试使用laravel在excel中导出大数据时显示超时

扩展 Kafka Connect 以处理 10K S3 存储桶

如何使用 Pandas 从 InfluxDB 检索超过 10k 行?

从 bigquery 导入到 google 表格限制为 10k 行