Laravel-datatables: Carga lenta cuando los datos superan los 1000

Creado en 20 ene. 2017  ·  13Comentarios  ·  Fuente: yajra/laravel-datatables

Resumen del problema o solicitud de función

Usé este complemento durante mucho tiempo. pero después de unos días me ralentizó (muy lento). Intento consultar> 1K datos. Sigue cargándose durante al menos 5 segundos o más para mostrar los datos. Ocurre también cuando cambia la paginación.

Fragmento de código del problema

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

Detalles del sistema

Océano digital $ 10.

  • Sistema operativo Ubuntu 16.04
  • PHP versión 7.1
  • Laravel Versión 5.3
  • Laravel-Datatables Versión más reciente
performance question

Comentario más útil

Sí, indexar y optimizar la consulta es la solución para un rendimiento lento. Y, por supuesto, evite usar la colección. ¡Gracias!

Todos 13 comentarios

Estoy enfrentando el mismo problema, con más de 1 registro lac en la base de datos. Pero mi consulta y mi escenario son un poco complejos. En mi tabla estoy mostrando datos de más de 3 tablas. Y estoy editando los valores de las columnas antes de convertir los datos en una tabla.

Este es el código para mi vista

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

En mi opinión, estoy usando un archivo blade personalizado para cargar Datatble JavaScript

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

En mi archivo blade de JavaScript, estoy llamando a una ruta para el procesamiento del lado del servidor, que genera un generador de consultas para mi tabla con uniones y luego llama a una función que representa la tabla.
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>

Función para construir el constructor de consultas

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
    }

Finalmente, la función que muestra datos en la tabla.

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

Esto funciona rápido para los primeros 500 registros, pero se vuelve lento cuando aumentan los datos.
Estoy usando php7, WAMP, mysql 5.7.14

@ssuhat Perdón por agregar este comentario largo, pero su problema parece el mismo que el mío y no quiero plantear un problema duplicado.

No estoy seguro de esto, pero también estoy usando Digital Ocean en mi aplicación de demostración y creo que la respuesta es un poco rápida. ¿Debe haber algo más sucediendo en su servidor? ¿Quizás intente verificar sus registros y los recursos de su servidor?

@yajra Estoy usando Laravel Forge para manejar mi servidor. Entonces creo que no es un problema del servidor.

@yajra ¿Tienes alguna sugerencia para mí?

Hola, tengo el mismo problema.

Estoy haciendo una selección de 8 campos con 3 combinaciones en una tabla de 25.000 registros y esto es lento. (8 segundos por 25 registros por página)

algunos consejos para acelerar el proceso? Gracias

¿Quizás podría habilitar el registro de consultas lentas y ver si hay alguna recomendación?

@ssuhat y @ mariani10 , es solo una sugerencia (ignora si ya lo has hecho). Consulta el tiempo de ejecución de tus consultas e intenta optimizarlas. En mi caso, la consulta que escribí fue lenta, por lo que hizo que la carga de la tabla de datos fuera lenta. Después de optimizar la consulta, ahora funciona más rápido.

Agregar índices puede ser la clave para mejores rendimientos

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

Sí, indexar y optimizar la consulta es la solución para un rendimiento lento. Y, por supuesto, evite usar la colección. ¡Gracias!

Solo para agregar a esta discusión, después de que se haya asegurado de pasar la consulta a Datatables (y no a la Colección, vea los comentarios arriba), sí, puede agregar índices, pero en realidad desea crear índices compuestos de las columnas está seleccionando. por ejemplo, desea un índice compuesto en las columnas foo, bar, created_at si su consulta se ve así SELECT foo, bar, MAX(created) WHERE ... GROUP BY foo, bar' . Cuando hice esto, descubrí que la velocidad de mi consulta se redujo en un 50%.

No hay forma de acelerar. Estoy usando la propia paginación de laravel 1000 registros y después de aplicar la tabla de datos y eliminar la paginación inferior de la tabla de datos de jquery. Eso esta bien para mi

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

Esta es la mejor solución.

¿Fue útil esta página
0 / 5 - 0 calificaciones