Laravel-datatables: Serverseitiger Export von 200000-Datensätzen

Erstellt am 31. März 2018  ·  19Kommentare  ·  Quelle: yajra/laravel-datatables

Zusammenfassung des Problems oder der Funktionsanforderung

Wenn 200000 aufzeichnet, wie Daten exportiert werden. Wenn ich Daten exportiere "Zulässige Speichergröße von 134217728 Bytes erschöpft", wird diese Ausnahme ausgelöst.

Welche anderen Möglichkeiten gibt es, große Datenmengen in yajra / datatable zu exportieren.

Bitte geben Sie eine andere Möglichkeit an, große Datenmengen zu exportieren.

Wir haben eine begrenzte Menge an RAM auf dem Server.

Code-Snippet des Problems

public function showData(ServiceDataTable $dataTable)
    {
        return $dataTable
            ->render('dataTable.renderDataTable');
    }

Systemdetails

  • Betriebssystem: Ubuntu 16.04
  • PHP-Version: 7.0.0
  • Laravel Version: 5.5
  • Laravel-Datatables Version: 8.0
  • Laravel-Datatables Buttons Version: 3.1
performance question

Alle 19 Kommentare

Sie müssen Ihren eigenen Excel-Datei-Builder implementieren, um diese Massenanforderung zu verarbeiten. In Ihrer ServiceDataTable-Klasse können Sie die Methode protected function buildExcelFile() überschreiben und möglicherweise einen Teil usw. ausführen. Weitere Informationen finden Sie in den Laravel-Excel-Dokumenten.

    /**
     * Build excel file and prepare for export.
     *
     * <strong i="7">@return</strong> \Maatwebsite\Excel\Writers\LaravelExcelWriter
     */
    protected function buildExcelFile()
    {
        /** <strong i="8">@var</strong> \Maatwebsite\Excel\Excel $excel */
        $excel = app('excel');

        return $excel->create($this->getFilename(), function (LaravelExcelWriter $excel) {
            $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
                $sheet->fromArray($this->getDataForExport());
            });
        });
    }

Ich denke, folgenden Code erstellen Ausnahme
$this->getDataForExport();
Ruft eine Ausnahme ab, wenn serverseitig editColumn() definiert oder verwendet wird
Es gibt 200000 Datensätze.
Gibt es eine andere Möglichkeit, Daten abzurufen, ohne mehr Speicher zu verarbeiten oder nicht zuzuweisen?
Ich habe folgenden Link, aber Yajra Yajra / Laravel-Datatables-Buttons: ^ 3.1 unterstützt Laravel / Excel: 3.0 noch nicht
https://laravel-excel.maatwebsite.nl/docs/3.0/export/queued

Es sollte einen Weg geben, der direkt aus der Abfrage oder auf beredte Weise exportiert.

Ich benutze Postman, um diese Operation aber nachzuahmen

Zulässige Speichergröße von 134217728 Bytes erschöpft

Ausnahme ausgelöst. Ich habe keine Zeilen, die zum Generieren von HTML verwendet wurden. Ich verwende rawColumns (), um HTML zu entkommen. Meine Abfrage dauert 0,420 ms in phpmyadmin und zuerst 1,4 Sekunden.

Wenn wir dies in die Warteschlange stellen können, sollten wir es auch in einem Ordner auf dem Server speichern und dann dem Benutzer den Link zum Herunterladen bereitstellen können.

Vielen Dank für die Antwort.

Ich verwende es in JQuery Datatable oder Yajra Datatable und möchte von der Serverseite exportieren.

Ich denke, es ist nicht möglich, in einem Ordner auf dem Server zu speichern, es gibt viele Probleme, die Probleme verursachen.

Ich brauche Daten-Streaming.

Die Datenmenge hat eine Antwortgröße von 20 MB oder mehr.

Meine Anforderungen sind ähnlich, aber ich möchte die Datei auf dem Server (oder S3) speichern und einen Link zum Herunterladen entweder in meinem Anwendungs-Dashboard oder per E-Mail angeben. Ich sehe die Möglichkeit, dies zu tun. Wenn ich etwas finde, werde ich es hier aktualisieren.

Ich habe ein Problem mit der serverseitigen Verarbeitung, die viel RAM verbraucht, und die Standardgröße für die Zuweisung des Skriptspeichers beträgt 60 MB.
Schauen Sie sich memory_limit in der php.ini an
Das Ausführungszeitlimit max_execution_time beträgt 60.
Nachdem Sie den Wert erhöht hatten, konnten Sie eine Anfrage über den serverseitigen Export stellen.

Ich habe die Excel-Funktion geändert, um die Datei zu speichern, anstatt sie herunterzuladen. Sie speichert die Datei im Ordner storage / export /.

public function excel()
{
    $this->buildExcelFile()->store('xls');
}

Derzeit habe ich keine große Datenmenge in meiner Entwicklungsumgebung. Können Sie die oben genannten Änderungen in Ihrem Setup vornehmen und prüfen, ob das Excel in diesem Ordner erstellt werden kann, ohne die Speicherobergrenze zu erreichen?

Eine andere Sache zu beachten ist, dass ich Laravel 5.1 verwende, also maatwebsite / excel Version 2.1

Was ich wirklich tun möchte, ist, dies stattdessen in die Warteschlange zu stellen und zur Seite mit der Meldung zurückzukehren, dass die Berichterstellung läuft, und der Link zum Herunterladen der Datei wird per E-Mail an Ihre registrierte ID gesendet. "

In der Version 2.1 bin ich mir nicht sicher, wie ich in die Warteschlange treten soll, aber ich habe festgestellt, dass sie " Queued Chunk " verwenden, aber ich bin nicht sicher, wie ich dies implementieren soll.

Also irgendwelche Updates dazu?

Also irgendwelche Updates dazu?

Wenn jemand Laravel Excel 3.0+ verwendet, funktioniert die obere Lösung nicht. Sie sollten also buildExcelFile() mit "Queued Export" überschreiben .

Oder ich habe etwas anderes getan, indem ich auch Chunking verwendet habe, aber indem ich mein Merkmal erstellt und CSV verwendet habe, um meine Arbeit zu erledigen, und dies ist ein Beispiel

irgendwelche Updates?

Ab Laravel 6 können Sie mit LazyCollections jeweils nur ein Element in den Speicher laden. Dies behebt das Problem, dass nicht genügend Speicher zur Verfügung steht.

Sie müssen nur die DataTable-Klasse erweitern und einen angepassten DataTablesExportHandler schreiben.

Schau dir meinen Kern an

Genießen!

@singhofmarco Kannst du ein Beispiel geben?

@singhofmarco Ich stimme zu, habe letztes Jahr ein v10-Projekt gestartet, das LazyCollections verwendet, es aber nicht atm fortsetzen kann.

Ich bin einen anderen Weg gegangen. Ich habe die CSV-Funktion überschrieben und DataTables jedes Mal mit einer Datenseite aufgerufen. Verwenden Sie fputcsv für die Ergebniszeilen, bis die Datei vollständig ist, und geben Sie dann einfach den Dateiinhalt in einer Laravel-Antwort zurück.

Das Speicherlimit wird nicht nur nie mehr erreicht (bis die CSV selbst über das PHP-Speicherlimit hinaus wächst, kann eine Streaming-Antwort weiter helfen), sondern es ist auch mehr als doppelt so schnell ......

@ameenross Wenn möglich, können Sie Ihren Code bitte teilen.

@karmendra Ich möchte lieber nicht, da es sich um eine ältere Version von Yajra Datatables handelt. Im Grunde genommen füge ich jedoch einige Seiten- und Längenwerte in der Anforderung zusammen und rufe den Code auf, der normalerweise eine Seite mit Daten für AJAX zurückgibt (in meinem Fall $this->ajax()->getData(true)['data'] ). Ich habe eine Basisklasse für Datentabellen, die die Yajra-Datentabellenklasse mit einer Funktion getCsv (beschlossen, die CSV-Funktion doch nicht zu überschreiben, aber das ist nicht wichtig). Dies erfolgt in einer Schleife, bis keine Seiten mehr vorhanden sind.

@ameenross Danke das ist hilfreich. Ich werde es versuchen.

Laravel Datatable :: v1.5.0
Hier ist meine Lösung basierend auf dem @ TheGeekyM- Kommentar. Ich lasse sie für den Fall, dass sie jemand anderem hilft.
Ich habe eine ChunkedDatatableExportHandler-Klasse erstellt, die FromQuery implementiert und dann die buildExcelFile-Methode in meinen ServiceDataTables überschreibt, um sie zu verwenden.

<?php

namespace App\DataTables;

use Yajra\DataTables\Services\DataTable;

class ServiceDataTable extends DataTable
{
  protected $exportClass = ChunkedDatatableExportHandler::class;

  protected function buildExcelFile()
  {
      $query = app()->call([$this, 'query']);
      $query = $this->applyScopes($query);

      $dataTable = app()->call([$this, 'dataTable'], compact('query'));
      $dataTable->skipPaging();
      $data_query = $dataTable->getFilteredQuery();

      return new $this->exportClass($data_query);
  }
}
<?php
namespace App\DataTables;

use Illuminate\Database\Query\Builder;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;

class ChunkedDatatableExportHandler implements FromQuery, WithHeadings
{
    use Exportable;

    /**
     * <strong i="11">@var</strong> Builder 
     */
    protected $query;

    /**
     * ChunkDatatablesExportHandler constructor.
     * <strong i="12">@param</strong> Builder $query
     */
    public function __construct(Builder $query)
    {
        $this->query = $query;
    }

    /**
     * <strong i="13">@return</strong> array
     */
    public function headings(): array
    {
        $first = $this->query()->first();

        if ($first) {
            return array_keys((array)$first);
        }

        return [];
    }

    /**
     * <strong i="14">@return</strong> Builder
     */
    public function query()
    {
        return $this->query;
    }
}
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

ghost picture ghost  ·  3Kommentare

t0n1zz picture t0n1zz  ·  3Kommentare

nasirkhan picture nasirkhan  ·  3Kommentare

sangnguyenplus picture sangnguyenplus  ·  3Kommentare

FilipeBorges1993 picture FilipeBorges1993  ·  3Kommentare