Laravel-datatables: Slow performance

Created on 12 Mar 2018  ·  8Comments  ·  Source: yajra/laravel-datatables

Summary of problem or feature request

Slow performance when loading 537 records
on page load : 4.34 seconds
on paginate : 3.98 seconds

"pageLength": 10
is there any possibility to limit rows per page like 10 from the query than when using pagination of datatable it will load the other 10 ... like the built in laravel pagination

PS : even if pagination is disabled the loading time still 4.34 seconds

Code snippet of problem

Controller

public function membresData()
    {

        $membres = Membre::
        join('equipes', 'equipes.id', '=', 'membres.equipe_id')
        ->join('laboratoires', 'laboratoires.id', '=', 'equipes.laboratoire_id')
        ->join('etablissements as e1', 'e1.id', '=', 'laboratoires.etablissement_id')
        ->leftjoin('etablissements as e2', 'e2.id', '=', 'membres.etablissement_id')
        ->leftjoin('profils', 'profils.id', '=', 'membres.profil_id')
        ->leftjoin('typemembres', 'typemembres.id', '=', 'membres.typemembre_id')
        ->select ('membres.id','equipes.axe_recherche','laboratoires.libelle','laboratoires.periode_accreditation_dd','laboratoires.periode_accreditation_df','e1.abbreviation as etablab','membres.nom', 'membres.prenom', 'membres.cv', 'membres.sujet', 'e2.abbreviation as etabmem', 'profils.typeprofil', 'membres.cin', 'membres.email','typemembres.typemembre')
        ->orderBy('axe_recherche', 'asc')
        ->get();

        if(request()->ajax()){
        return Datatables::of($membres)

         ->addColumn('name', 
                '{{$nom}} {{$prenom}}'
            )

         ->addColumn('cv', function ($membre) {
            if ($membre->cv != null){
            $url=url("uploadedCvMembre/$membre->etablab/$membre->cv");
            return '<div data-provide="photoswipe">
                        <img class="avatar avatar-sm cursor-pointer" src="'.$url.'" alt="Curriculum vitae de : '.$membre->prenom.' '.$membre->nom.'" data-provide="tooltip" data-original-title="Curriculum vitae" data-tooltip-color="primary" aria-describedby="tooltip946475">

                    </div>   ';
            }        
         })

         ->addColumn('laboratoire',
                '« {{$etablab}} » {{ $libelle }} <small>{{ \Carbon\Carbon::parse($periode_accreditation_dd)->format("Y") }} - {{ \Carbon\Carbon::parse($periode_accreditation_df)->format("Y") }}</small>'
            )

         ->addColumn('action', 
            '<nav class="nav gap-1 fs-16">


                            <a class="nav-link disabled hover-warning" data-provide="tooltip" data-tooltip-color="warning" data-original-title="Modifier" href="{{route("membre.edit",$id)}}"><i class="ti-pencil"></i></a>



                            <form method="POST" action="{{ action("MembreController@destroy", ["id" => $id]) }}" class="delete_form">
                            @csrf
                            @method("DELETE")
                            <a class="nav-link disabled hover-danger delete-btn" data-provide="tooltip" data-tooltip-color="danger" data-original-title="Supprimer" href="#"><i class="ti-trash"></i></a>
                            </form>


            </nav>'
        )

         ->rawColumns(['cv','laboratoire','action'])
         ->make(true);
        }else{
            abort('404');
        }

Js

app.ready(function(){
        $("#dtable").dataTable().fnDestroy();
        $('#dtable').DataTable({
        "columnDefs": [
            { "visible": false, "targets": [0,1] },
            { "orderable": false, "targets": [-1] }
        ],
        "order": [[ 1, 'asc' ]],
        processing: true,
        serverSide: true,
        ajax: '{!! route('membres') !!}',
        deferRender: true,
        columns: [
            { data: 'laboratoire', name: 'laboratoire' },
            { data: 'axe_recherche', name: 'axe_recherche' },
            { data: 'name', name: 'name' },
            { data: 'cv', name: 'cv', orderable: false, searchable: false },
            { data: 'sujet', name: 'sujet' },
            { data: 'etabmem', name: 'etabmem', orderable: false, searchable: false },
            { data: 'typeprofil', name: 'typeprofil' },
            { data: 'cin', name: 'cin' },
            { data: 'email', name: 'email' },
            { data: 'typemembre', name: 'typemembre' },
            { data: 'action', name: 'action', orderable: false, searchable: false}

        ],
        "drawCallback": function ( settings ) {
            $('[data-provide~="tooltip"]').each(function(){var b="";$(this).hasDataAttr("tooltip-color")&&(b=" tooltip-"+$(this).data("tooltip-color")),$(this).tooltip({container:"body",trigger:"hover",template:'<div class="tooltip'+b+'" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'})});
            var api = this.api();
            var rows = api.rows( {page:'current'} ).nodes();
            var last=null;

            api.column(0, {page:'current'} ).data().each( function ( group, i ) {
                if ( last !== group ) {
                    $(rows).eq( i ).before(
                        '<tr class="group bl-3 br-3 border-primary bg-light text-center" ><td class="fw-500" colspan="9">'+group+'</td></tr>'
                    );

                    last = group;
                }
            } );
            api.column(1, {page:'current'} ).data().each( function ( group, i ) {
                if ( last !== group ) {
                    $(rows).eq( i ).before(
                        '<tr class="group bl-3 border-warning bg-light" ><td class="fw-500" colspan="9">Equipe : '+group+'</td></tr>'
                    );

                    last = group;
                }
            } );

        }
    });


  });

System details

  • Operating System Ubuntu 17.10
  • PHP 7.2.2
  • Laravel 5.6
  • Laravel-Datatables 8.4
performance question

Most helpful comment

Use query instead of collection by removing get() on your data source.

>orderBy('axe_recherche', 'asc')
        ->get(); // remove this line.

All 8 comments

Use query instead of collection by removing get() on your data source.

>orderBy('axe_recherche', 'asc')
        ->get(); // remove this line.

@yajra Thank you problem solved

hi can you explain why query is much faster than collection?

Because it performs the rest of the functions on the query instead of getting every result and its sub data and trying to perform the functions on that which is less efficient.

Response time is slow
page-load : 13.40s
pagination: 9s
Code Snippet

Controller

public function lending_return_log_server_side()
{
$alluser = Session::get('alluser');
$reference = $this->database->getReference('lending_return_log')->getSnapshot()->getValue();
$reference = array_reverse($reference);
$data = [];
$name = '';
$email = '';
foreach ($reference as $lending_return_log) {
// dd($lending_return_log['uid']);
foreach ($alluser as $key => $value) {
if ($key == $lending_return_log['uid']) {
$name = $value['username'];
$email = $value['email'];
}
}
$nestedData['user_info'] = "". $name. "
". $email."
". $lending_return_log['lending_log_id'];
$nestedData['time_and_trx_id'] = \Carbon\Carbon::parse($lending_return_log['time'])->format('F j, Y, g:i a')."
".$lending_return_log['trxid']."";
$nestedData['back_amount'] = "".number_format($lending_return_log['amount_back_nob'],8)." NOB";
$nestedData['closing_balance'] = "".number_format($lending_return_log['final_balance_nob'],8)." NOB";
$nestedData['nob_price'] = $lending_return_log['nob_price_at']."$";
$nestedData['curr_return'] = "".number_format($lending_return_log['return_of_cur'],8)." ".$lending_return_log['cur_type']."";

        $data[] = $nestedData;
    }
    // $reference = collect($reference);

    $finalData = Datatables::of($data)->rawColumns(['user_info', 'time_and_trx_id', 'back_amount', 'closing_balance', 'nob_price', 'curr_return'])->make(true);
    return $finalData;
}

JS

(function() {
$('#table').DataTable({
processing: true,
serverSide: true,
ajax: '{{ url('project-log-serverside') }}',
columns: [
{ data: 'user_info', name: 'user_info' },
{ data: 'time_and_trx_id', name: 'time_and_trx_id' },
{ data: 'back_amount', name: 'back_amount' },
{ data: 'closing_balance', name: 'closing_balance' },
{ data: 'nob_price', name: 'nob_price' },
{ data: 'curr_return', name: 'curr_return' },
]
});
});

Package versions
Laravel 5.7
PHP: 7.2
Laravel Datatable : 8.13.7
Database: NoSql DB(Firebase)

Can you please what's wrong in this?
Thanks

Check your indexing

Controller:
$trade1 = Tradecum3::where('CODE', Auth::user()->ucc_code)->where('SCPOPT','!=','EX')->select('UNIQUEID', 'CODE', 'TRDATE', 'BS', 'SCPOPT as INSTTYPE','SCPCODE','SCPNAME', 'DUEDATE', 'STRIKERATE', 'MKTRATE', 'QTY', DB::raw('ABS(MKTRATE * QTY) as MKTTOTAL'));

    $trade2 = Tradecum2::where('CODE', Auth::user()->ucc_code)->where('SCPOPT', '!=', 'EX')->select('UNIQUEID', 'CODE', 'TRDATE', 'BS', 'SCPOPT as INSTTYPE', 'SCPCODE', 'SCPNAME', 'DUEDATE', 'STRIKERATE', 'MKTRATE', 'QTY', DB::raw('ABS(MKTRATE * QTY) as MKTTOTAL'));

    $trade = Tradecum1::where('CODE', Auth::user()->ucc_code)->where('SCPOPT', '=', 'EQ')->select('UNIQUEID', 'CODE', 'TRDATE', 'BS', 'SCPOPT as INSTTYPE', 'SCPCODE', 'SCPNAME', 'DUEDATE', 'STRIKERATE', 'MKTRATE', 'QTY', DB::raw('ABS(MKTRATE * QTY) as MKTTOTAL'))->union($trade1)->union($trade2);


    return DataTables::of($trade)
      ->addColumn('INSTNAME', function ($trade) {
       return $trade->SCPNAME."(". $trade->SCPCODE.")";
      })
      ->editColumn('INSTTYPE',function($trade){
        if($trade->INSTTYPE == "CE")
          return "Call Opt";
        else if ($trade->INSTTYPE == "PE")
          return "Put Opt";
        else if ($trade->INSTTYPE == "CF")
          return "Futures(EQ)";
      else if ($trade->INSTTYPE == "IF")
        return "Futures(INDEX)";
      else
        return $trade->INSTTYPE;
      })
  ->rawColumns(['INSTNAME'])
    ->make(true);

View:
$('#recentTradeTableAll').DataTable({
processing: true,
serverSide: true,
destroy: true,
ajax: {
url: "{{ route('datatable.trades') }}",
type: 'POST',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: function(d) {

                d.instrumentType = $("input[name='instrumentType']:checked").val();
                d.transaction_type = $("input[name='transaction_type']:checked").val();
            }
        },
        columns: [{
                data: 'TRDATE',
                name: 'TRDATE'
            },
            {
                data: 'BS',
                name: 'BS'
            },
            {
                data: 'INSTNAME',
                name: 'INSTNAME'
            },
            {
                data: 'STRIKERATE',
                name: 'STRIKERATE'
            },
            {
                data: 'INSTTYPE',
                name: 'INSTTYPE'
            },
            {
                data: 'DUEDATE',
                name: 'DUEDATE'
            },
            {
                data: 'MKTRATE',
                name: 'MKTRATE'
            },
            {
                data: 'QTY',
                name: 'QTY'
            },
            {
                data: 'MKTTOTAL',
                name: 'MKTTOTAL'
            }
        ]
    });

get() loads all the data and pageLength is not working..the above is loading all record.

Use query instead of collection by removing get() on your data source.

>orderBy('axe_recherche', 'asc')
        ->get(); // remove this line.

This made my query go from 20 seconds to under 2. Thank you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vipin733 picture vipin733  ·  3Comments

jackrsantana picture jackrsantana  ·  3Comments

Mopster picture Mopster  ·  3Comments

macnux picture macnux  ·  3Comments

sangnguyenplus picture sangnguyenplus  ·  3Comments