Laravel-datatables: تحميل بطيء عندما تكون البيانات أكثر من 1000

تم إنشاؤها على ٢٠ يناير ٢٠١٧  ·  13تعليقات  ·  مصدر: yajra/laravel-datatables

ملخص المشكلة أو طلب الميزة

لقد استخدمت هذا البرنامج المساعد لفترة طويلة جدًا. ولكن بعد أيام قليلة تبطئني (بطيئة حقًا). أحاول الاستعلام> 1K البيانات. استمر في التحميل لمدة 5 ثوانٍ على الأقل أو أكثر لعرض البيانات. يحدث ذلك عند تغيير ترقيم الصفحات أيضًا.

مقتطف رمز المشكلة

public function getData()
{
    $brands = Brand::select('id', 'name');

    return Datatables::of($brands)
        ->addColumn('action', function ($brand) {
            return '
            <a href="/brands/' . $brand->id . '/edit" class="btn btn-xs btn-primary">
                <i class="fa fa-pencil"></i> Edit
            </a>
            <a href="#" id="delete-button" data-id="' . $brand->id . '" class="btn btn-xs btn-danger">
            <i class="fa fa-times"></i> Delete
            </a>
            ';
        })
        ->make(true);
}

تفاصيل النظام

المحيط الرقمي 10 دولارات.

  • نظام التشغيل أوبونتو 16.04
  • إصدار PHP 7.1.1
  • إصدار Laravel 5.3.1
  • إصدار Laravel-Datatables الأحدث
performance question

التعليق الأكثر فائدة

نعم ، تعد فهرسة الاستعلام وتحسينه حلاً لبطء الأداء. وبالطبع تجنب استخدام الجمع. شكر!

ال 13 كومينتر

أواجه نفس المشكلة ، مع أكثر من 1 من سجلات lac في قاعدة البيانات. لكن استفساري وسيناريوهات معقدة بعض الشيء. أعرض في الجدول الخاص بي بيانات من أكثر من 3 جداول. وأنا أقوم بتحرير قيم العمود قبل تحويل البيانات إلى الجدول.

هذا هو رمز وجهة نظري

   /**
     * 
     *
     * function to return table view
     */
    public function inbox_ticket_list() {
        $table = \Datatable::table()
                ->addColumn(
                        "", Lang::get('lang.subject'), Lang::get('lang.ticket_id'), Lang::get('lang.priority'), Lang::get('lang.from'), Lang::get('lang.assigned_to'), Lang::get('lang.last_activity'), Lang::get('lang.created-at'))
                ->noScript();

        return view('themes.default1.agent.helpdesk.ticket.inbox', compact('table'));
    }

من وجهة نظري ، أستخدم ملف نصلي مخصص لتحميل Datatble JavaScript

{!!$table->render('vendor.Chumper.template')!!}
{!! $table->script('vendor.Chumper.ticket-javascript') !!}

في ملف JavaScript النصلي الخاص بي ، أقوم باستدعاء مسار للمعالجة من جانب الخادم ، والذي يقوم بإنشاء منشئ استعلام لجدولي باستخدام الصلات ثم استدعاء دالة تقوم بعرض الجدول.
تذكرة javascript.blade

<?php
$segments = \Request::segments();
$segment = "";
foreach($segments as $seg){
    $segment.="/".$seg;
}
?>
<script type="text/javascript">
        function myFunction()
        {
            return jQuery('#chumper').dataTable({
                "sDom": "<'row'<'col-xs-6'l><'col-xs-6'f>r>"+
                        "t"+
                        "<'row'<'col-xs-6'i><'col-xs-6'p>>",
                "sPaginationType": "full_numbers",
                "bProcessing": true,
                "bServerSide": true,
                "lengthMenu": [[10, 25, 50, 100, 500], [10, 25, 50, 100, 500]],
                "ajax": {
                    url: "{{url('filter')}}",
                    data: function (d) {
                        d.labels = $('select[name=label]').val();
                        d.tags = $('select[name=tag]').val();
                        d.segment = "{{$segment}}";
                    }
                },
                "aaSorting": sort,
                "columnDefs": [
                    { "searchable": false, "targets": [6,7] },
                    { "visible": last, "targets": 6 },
                    {"visible": create, "targets":7},
                ],
                "fnCreatedRow": function (nRow, aData, iDataIndex) {
                    var str = aData[3];
                    if (str.search("#000") == -1) {
                        $("td", nRow).css({"background-color": "#F3F3F3", "font-weight": "600", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px #F3F3F3"});
                        $("td", nRow).mouseenter(function () {
                            $("td", nRow).css({"background-color": "#DEDFE0", "font-weight": "600", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px #DEDFE0"});
                        });
                        $("td", nRow).mouseleave(function () {
                            $("td", nRow).css({"background-color": "#F3F3F3", "font-weight": "600", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px #F3F3F3"});
                        });
                    } else {
                        $("td", nRow).css({"background-color": "white", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px white"});
                        $("td", nRow).mouseenter(function () {
                            $("td", nRow).css({"background-color": "#DEDFE0", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px #DEDFE0"});
                        });
                        $("td", nRow).mouseleave(function () {
                            $("td", nRow).css({"background-color": "white", "border-bottom": "solid 0.5px #ddd", "border-right": "solid 0.5px white"});
                        });
                    }
                }
            });
        }
</script>

وظيفة لبناء أداة إنشاء الاستعلام

public function table(){
        // if (Auth::user()->role == 'admin') {
            $ticket = new Tickets();
            $tickets = $ticket
                    ->leftJoin('ticket_thread', function ($join) {
                        $join->on('tickets.id', '=', 'ticket_thread.ticket_id')
                        ->whereNotNull('title')
                        ->where('ticket_thread.is_internal', '<>', 1);
                    })
                    ->leftJoin('ticket_thread as ticket_thread2', 'ticket_thread2.ticket_id', '=', 'tickets.id')
                    ->Join('ticket_source', 'ticket_source.id', '=', 'tickets.source')
                    ->leftJoin('ticket_priority', 'ticket_priority.priority_id', '=', 'tickets.priority_id')
                    ->leftJoin('users as u', 'u.id', '=', 'tickets.user_id')
                    ->leftJoin('users as u1', 'u1.id', '=', 'tickets.assigned_to')
                    ->leftJoin('ticket_attachment', 'ticket_attachment.thread_id', '=', 'ticket_thread.id')
                    ->leftJoin('teams', 'teams.id', '=', 'tickets.team_id')
                    ->leftJoin('ticket_collaborator', 'ticket_collaborator.ticket_id', '=', 'tickets.id')
                    ->select(
                        'tickets.id',
                        // 'tickets.team_id',
                        'ticket_thread.title',
                        'tickets.ticket_number',
                        'ticket_priority.priority',
                        'u.user_name as user_name',
                        'u1.user_name as assign_user_name',
                        \DB::raw('max(ticket_thread.updated_at) as updated_at'),
                        \DB::raw('min(ticket_thread.updated_at) as created_at'),
                        'u.first_name as first_name',                        
                        'u.last_name as last_name',
                        'u1.first_name as assign_first_name',
                        'u1.last_name as assign_last_name',
                        'ticket_priority.priority_color',
                        'teams.name',
                        DB::raw('COUNT(DISTINCT ticket_thread2.id) as countthread'),
                        DB::raw('COUNT(ticket_attachment.thread_id) as countattachment'),
                        DB::raw('COUNT(ticket_collaborator.ticket_id) as countcollaborator'),
                        'tickets.status',
                        'tickets.user_id',
                        'tickets.priority_id', 'tickets.assigned_to',
                        'ticket_status.name as tickets_status',
                        'ticket_source.css_class as css',
                        DB::raw('substring_index(group_concat(ticket_thread.poster order by ticket_thread.id desc) , ",", 1) as last_replier'),
                        DB::raw('substring_index(group_concat(ticket_thread.title order by ticket_thread.id asc) , ",", 1) as ticket_title'),
                        'u.active as verified')
                    ->groupby('tickets.id');
        return \Ttable::getTable($table); // call to function which renders table
    }

أخيرًا الوظيفة التي تعرض البيانات في الجدول

public static function getTable($tickets) {
        return \Datatables::of($tickets)
                        ->addColumn('id', function ($tickets) {
                            return "<input type='checkbox' name='select_all[]' id='" . $tickets->id . "' onclick='someFunction(this.id)' class='selectval icheckbox_flat-blue' value='" . $tickets->id . "'></input>";
                        })
                        ->addColumn('title', function ($tickets) {
                            if (isset($tickets->ticket_title)) {
                                $string = mb_substr($tickets->ticket_title, 0, 20, 'UTF-8');
                            } else {
                                $string = Lang::get('lang.no-subject');
                            }
                            $collab = $tickets->countcollaborator;
                            if ($collab > 0) {
                                $collabString = '&nbsp;<i class="fa fa-users"></i>';
                            } else {
                                $collabString = null;
                            }
                            $attachCount = $tickets->countattachment;
                            if ($attachCount > 0) {
                                $attachString = '&nbsp;<i class="fa fa-paperclip"></i>';
                            } else {
                                $attachString = '';
                            }
                            $css = $tickets->css;
                            $titles = '';
                            if ($tickets->ticket_title) {
                                $titles = $tickets->ticket_title;
                            }
                            $tooltip_script = self::tooltip($tickets->id);
                            return "<div class='tooltip1' id='tool" . $tickets->id . "'>
                            <a href='" . route('ticket.thread', [$tickets->id]) . "'>" . ucfirst($string) . "&nbsp;<span style='color:green'>(" . $tickets->countthread . ") <i class='" . $css . "'></i></span>
                            </a>" . $collabString . $attachString . $tooltip_script .
                                    "<span class='tooltiptext'  id='tooltip" . $tickets->id . "'>Loading...</span></div>";
                        })
                        ->addColumn('ticket_number', function ($tickets) {
                            return "<a href='" . route('ticket.thread', [$tickets->id]) . "' title='" . $tickets->ticket_number . "'>#" . $tickets->ticket_number . '</a>';
                        })
                        ->addColumn('priority', function ($tickets) {
                            $rep = ($tickets->last_replier == 'client') ? '#F39C12' : '#000';
                            $priority = $tickets->priority;
                            if ($priority != null) {
                                $prio = '<button class="btn btn-xs ' . $rep . '" style="background-color: ' . $tickets->priority_color . '; color:#F7FBCB">' . ucfirst($tickets->priority) . '</button>';
                            } else {
                                $prio = $tickets->last_relier_role;
                            }
                            return $prio;
                        })
                        ->addColumn('user_name', function ($tickets) {
                            $from = $tickets->first_name;
                            $url = route('user.show', $tickets->user_id);
                            $name = $tickets->user_name;
                            if ($from) {
                                $name = utfEncoding($tickets->first_name) . ' ' . utfEncoding($tickets->last_name);
                            }
                            $color = '';
                            if ($tickets->verified == 0 || $tickets->verified == '0') {
                                $color = "<i class='fa fa-exclamation-triangle'  title='" . Lang::get('lang.accoutn-not-verified') . "'></i>";
                            }
                            return "<a href='" . $url . "' title='" . Lang::get('lang.see-profile1') . ' ' . ucfirst($name) . '&apos;' . Lang::get('lang.see-profile2') . "'><span style='color:#508983'>" . ucfirst(str_limit($name, 30)) . ' <span style="color:#f75959">' . $color . '</span></span></a>';
                        })
                        ->addColumn('assign_user_name', function ($tickets) {
                            if ($tickets->assigned_to == null && $tickets->name == null) {
                                return "<span style='color:red'>Unassigned</span>";
                            } else {
                                $assign = $tickets->assign_user_name;
                                if ($tickets->assigned_to != null) {
                                    $assign = utfEncoding($tickets->assign_first_name) . ' ' . utfEncoding($tickets->assign_last_name);

                                $url = route('user.show', $tickets->assigned_to);
                                return "<a href='" . $url . "' title='" . Lang::get('lang.see-profile1') . ' ' . ucfirst($assign) . '&apos;' . Lang::get('lang.see-profile2') . "'><span style='color:green'>" . mb_substr(ucfirst($assign), 0, 30, 'UTF-8') . '</span></a>';
                            } else{
                                $url1 = "#";
                                return "<a href='" . $url1 . "' title='" . Lang::get('lang.see-profile1') . ' ' . ucfirst($tickets->name) . '&apos;' . Lang::get('lang.see-profile2') . "'><span style='color:green'>" . mb_substr(ucfirst($tickets->name), 0, 30, 'UTF-8') . '</span></a>';


                                }
                            }
                        })
                        ->addColumn('updated_at', function ($tickets) {
                            $TicketDatarow = $tickets->updated_at;
                            $updated = '--';
                            if ($TicketDatarow) {
                                $updated = $tickets->updated_at;
                            }
                            return '<span style="display:none">' . $updated . '</span>' . UTC::usertimezone($updated);
                        })
                        ->addColumn('created_at', function ($tickets) {
                            $TicketDatarow = $tickets->created_at;
                            $updated = '--';
                            if ($TicketDatarow) {
                                $updated = $tickets->created_at;
                            }
                            return '<span style="display:none">' . $updated . '</span>' . UTC::usertimezone($updated);
                        })
                        ->make();
    }

يعمل هذا بسرعة لأول 500 سجل ولكنه يصبح بطيئًا بعد زيادة البيانات.
أنا أستخدم php7، WAMP، mysql 5.7.14

ssuhat آسف لإضافة هذا التعليق الطويل ، لكن مشكلتك تبدو مماثلة

لست متأكدًا حقًا من هذا ولكني أستخدم Digital Ocean أيضًا في تطبيق العرض التجريبي والاستجابة سريعة بعض الشيء على ما أعتقد. هل يجب أن يكون هناك شيء آخر يحدث على الخادم الخاص بك؟ ربما تحاول التحقق من سجلاتك وموارد الخادم الخاص بك؟

yajra أنا أستخدم Laravel Forge للتعامل مع خادمي. لذلك أعتقد أنها ليست مشكلة الخادم.

yajra هل لديك أي اقتراح لي؟

مرحبا، انا عندي نفس المشكلة.

أنا أقوم بتحديد 8 حقول مع 3 الانضمام في جدول يحتوي على 25.000 سجل وهذا ببطء. (8 ثوانٍ لكل 25 سجلًا لكل صفحة)

بعض النصائح لتسريع الشيء؟ شكر

ربما يمكنك تمكين سجل الاستعلامات البطيء ومعرفة ما إذا كان هناك أي توصية؟

ssuhat و @ mariani10 ، إنه مجرد اقتراح (تجاهل إذا كنت قد فعلت ذلك بالفعل). تحقق من وقت تنفيذ استفساراتك وحاول تحسينها. في حالتي ، كان الاستعلام الذي كتبته بطيئًا لذا جعل تحميل البيانات بطيئًا. بعد تحسين الاستعلام ، يعمل بشكل أسرع الآن.

يمكن أن تكون إضافة الفهارس هي المفتاح لتحسين الأداء

يحل محل:
$brands = Brand::select('id', 'name');
=> $brands = Brand::query();

نعم ، تعد فهرسة الاستعلام وتحسينه حلاً لبطء الأداء. وبالطبع تجنب استخدام الجمع. شكر!

فقط للإضافة إلى هذه المناقشة ، بعد التأكد من تمرير الاستعلام إلى Datatables (وليس المجموعة - انظر التعليقات أعلاه) - نعم ، يمكنك إضافة فهارس ، لكنك تريد بالفعل إنشاء فهارس مركبة للأعمدة التي تريدها ' إعادة الاختيار. على سبيل المثال ، تريد فهرسًا مركبًا على الأعمدة foo ، bar ، created_at إذا كان استعلامك يبدو مثل SELECT foo, bar, MAX(created) WHERE ... GROUP BY foo, bar' . عندما فعلت ذلك ، وجدت أن سرعة استفساري قد انخفضت بنسبة 50٪.

لا توجد طريقة للحصول بسرعة. أنا أستخدم ترقيم صفحات لارافيل 1000 سجل خاص به وبعد تطبيق ترقيم صفحات قاعدة البيانات وإزالة ترقيم الصفحات السفلية القابلة للتسجيل. هذا جيد بالنسبة لي

يحل محل:
$brands = Brand::select('id', 'name');
=> $brands = Brand::query();

هذا هو الحل الافضل.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات