Laravel-datatables: Langsames Laden bei Daten über 1000

Erstellt am 20. Jan. 2017  ·  13Kommentare  ·  Quelle: yajra/laravel-datatables

Zusammenfassung des Problems oder der Funktionsanforderung

Ich habe dieses Plugin sehr lange benutzt. aber nach ein paar Tagen verlangsamt es mich (sehr langsam). Ich versuche> 1K Daten abzufragen. Es wird mindestens 5 Sekunden oder länger geladen, um die Daten anzuzeigen. Es passiert auch, wenn die Paginierung geändert wird.

Code-Snippet des Problems

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);
}

Systemdetails

Digital Ocean $ 10.

  • Betriebssystem Ubuntu 16.04
  • PHP Version 7.1
  • Laravel Version 5.3
  • Laravel-Datatables Version Neueste
performance question

Hilfreichster Kommentar

Ja, das Indizieren und Optimieren der Abfrage ist die Lösung für langsame Leistung. Und natürlich vermeiden Sie die Verwendung der Sammlung. Vielen Dank!

Alle 13 Kommentare

Ich habe das gleiche Problem mit mehr als 1 Lac-Datensätzen in der Datenbank. Aber meine Abfrage und mein Szenario sind etwas komplex. In meiner Tabelle zeige ich Daten aus mehr als 3 Tabellen. Und ich bearbeite Spaltenwerte, bevor ich die Daten in eine Tabelle rendere.

Dies ist der Code für meine Ansicht

   /**
     * 
     *
     * 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'));
    }

Aus meiner Sicht verwende ich eine benutzerdefinierte Blade-Datei zum Laden von Datatble JavaScript

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

In meiner JavaScript-Blade-Datei rufe ich eine Route für die serverseitige Verarbeitung auf, die einen Abfrage-Generator für meine Tabelle mit Verknüpfungen generiert und dann eine Funktion aufruft, die die Tabelle rendert.
ticket-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>

Funktion zum Erstellen eines Querybuilders

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
    }

Endlich die Funktion, die Daten in der Tabelle rendert

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();
    }

Dies funktioniert bei den ersten 500 Datensätzen schnell, wird jedoch nach Datenerhöhung langsam.
Ich benutze PHP7, WAMP, MySQL 5.7.14

@ssuhat Entschuldigen Sie, dass Sie diesen langen Kommentar hinzugefügt haben, aber Ihr Problem scheint dasselbe zu sein wie meins, und ich möchte kein doppeltes Problem dafür aufwerfen.

Ich bin mir nicht sicher, aber ich verwende Digital Ocean auch in meiner Demo-App und die Antwort ist meiner Meinung nach etwas schnell. Muss noch etwas auf Ihrem Server passieren? Versuchen Sie vielleicht, Ihre Protokolle und Serverressourcen zu überprüfen?

@yajra Ich benutze Laravel Forge, um meinen Server zu verwalten. Ich denke, es ist kein Serverproblem.

@yajra Hast du einen Vorschlag für mich?

Hallo, ich habe das gleiche Problem.

Ich wähle 8 Felder mit 3 Joins in einer Tabelle mit 25.000 Datensätzen aus und das ist langsam. (8 Sekunden pro 25 Datensätze pro Seite)

einige Tipps zur Beschleunigung der Sache? Vielen Dank

Vielleicht könnten Sie das Protokoll für langsame Abfragen aktivieren und prüfen, ob eine Empfehlung vorliegt?

@ssuhat und @ mariani10 , es ist nur ein Vorschlag (ignorieren, wenn Sie es bereits getan haben). Überprüfen Sie die Ausführungszeit Ihrer Abfragen und versuchen Sie, diese zu optimieren. In meinem Fall war die von mir geschriebene Abfrage langsam, sodass das Laden von Daten langsam wurde. Nach der Optimierung der Abfrage funktioniert sie jetzt schneller.

Das Hinzufügen von Indizes kann der Schlüssel zu besseren Leistungen sein

Ersetzen:
$brands = Brand::select('id', 'name');
=> $brands = Brand::query();

Ja, das Indizieren und Optimieren der Abfrage ist die Lösung für langsame Leistung. Und natürlich vermeiden Sie die Verwendung der Sammlung. Vielen Dank!

Nur um diese Diskussion zu ergänzen, nachdem Sie sichergestellt haben, dass Sie die Abfrage an Datatables (und nicht an die Sammlung - siehe Kommentare oben) übergeben haben - ja, Sie können Indizes hinzufügen, aber Sie möchten tatsächlich zusammengesetzte Indizes der Spalten erstellen, die Sie ' erneut auswählen. Beispiel: Sie möchten einen zusammengesetzten Index für die Spalten foo, bar, created_at, wenn Ihre Abfrage so aussieht: SELECT foo, bar, MAX(created) WHERE ... GROUP BY foo, bar' . Als ich dies tat, stellte ich fest, dass meine Abfragegeschwindigkeit um 50% reduziert wurde.

Es gibt keine Möglichkeit, schnell zu werden. Ich verwende eigene Laravel-Paginierungs-1000-Datensätze und nach dem Anwenden einer datierbaren und entfernten jquery-datierbaren unteren Paginierung. Das ist gut für mich

Ersetzen:
$brands = Brand::select('id', 'name');
=> $brands = Brand::query();

Dies ist die beste Lösung.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

SGarridoDev picture SGarridoDev  ·  3Kommentare

Mopster picture Mopster  ·  3Kommentare

t0n1zz picture t0n1zz  ·  3Kommentare

Abdulhmid picture Abdulhmid  ·  3Kommentare

shadoWalker89 picture shadoWalker89  ·  3Kommentare