Laravel-datatables: Export côté serveur 200000 enregistrements

Créé le 31 mars 2018  ·  19Commentaires  ·  Source: yajra/laravel-datatables

Résumé du problème ou de la demande de fonctionnalité

Lorsque 200000 enregistre comment exporter des données. Lorsque j'exporte des données "La taille de mémoire autorisée de 134217728 octets épuisée", cette exception est levée.

Quelles sont les autres options pour exporter une grande quantité de données dans yajra / datatable.

Veuillez fournir une méthode différente pour exporter une grande quantité de données.

Nous avons une quantité limitée de RAM sur le serveur.

Extrait de code du problème

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

Détails du système

  • Système d'exploitation: Ubuntu 16.04
  • Version PHP: 7.0.0
  • Version de Laravel: 5.5
  • Version Laravel-Datatables: 8.0
  • Boutons Laravel-Datatables Version: 3.1
performance question

Tous les 19 commentaires

Vous devez implémenter votre propre générateur de fichiers Excel pour gérer cette demande en masse. Sur votre classe ServiceDataTable, vous pouvez remplacer la méthode protected function buildExcelFile() et peut-être faire un morceau, etc. Voir la documentation laravel-excel pour plus d'informations.

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

Je pense que le code suivant crée une exception
$this->getDataForExport();
Obtient une exception lorsque editColumn() côté serveur est défini ou utilisé
il y a 200 000 enregistrements.
Existe-t-il un autre moyen d'obtenir des données sans traitement ou sans allouer plus de mémoire.
J'ai le lien suivant mais yajra yajra / laravel-datatables-buttons: ^ 3.1 pas encore supporté Laravel / Excel: 3.0
https://laravel-excel.maatwebsite.nl/docs/3.0/export/queued

Il devrait y avoir un moyen d'exporter directement à partir de la requête ou de manière éloquente.

J'utilise Postman pour imiter cette opération mais

Taille de mémoire autorisée de 134217728 octets épuisés

exception levée. Je n'ai pas de lignes utilisées pour générer du HTML, j'utilise rawColumns () pour échapper au HTML, Ma requête prend 0,420 ms en phpmyadmin et Au début 1,4 sec.

Si nous sommes en mesure de le mettre en file d'attente, nous devrions également pouvoir l'enregistrer dans un dossier sur le serveur, puis fournir le lien à l'utilisateur pour le télécharger.

Merci de votre réponse.

Je l'utilise dans JQuery Datatable ou yajra datatable et je souhaite exporter du côté serveur.

Je pense qu'il n'est pas possible d'enregistrer dans un dossier sur le serveur, il y a de nombreux problèmes qui vont générer des problèmes.

J'ai besoin de streaming de données.

La quantité de données est de taille 20 Mo en réponse ou plus.

Mon exigence est similaire, mais je voudrais enregistrer le fichier sur le serveur (ou S3) et donner un lien pour le télécharger soit dans le tableau de bord de mon application, soit par e-mail. Je vois la possibilité de le faire, si je trouve quelque chose, je vais mettre à jour ici.

J'ai un problème avec le traitement côté serveur qui consomme une grande quantité de RAM et la taille d'allocation de mémoire de script par défaut est de 60 Mo.
Regardez memory_limit dans php.ini
Le délai d'exécution max_execution_time est de 60.
Après avoir augmenté la valeur, vous avez pu faire une demande en utilisant l'exportation côté serveur.

J'ai modifié la fonction Excel pour stocker le fichier au lieu de le télécharger, il stocke le fichier dans le dossier stockage / exportations /.

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

actuellement, je n'ai pas une grande quantité de données dans mon environnement de développement, pouvez-vous apporter les modifications ci-dessus dans votre configuration et voir s'il est capable de créer le fichier Excel dans ce dossier sans atteindre le plafond de la mémoire?

Une autre chose à noter est que j'utilise Laravel 5.1 donc maatwebsite / excel version 2.1

Ce que je veux vraiment faire, c'est mettre cela dans la file d'attente à la place et revenir à la page avec un message indiquant que la création du rapport est en cours et le lien pour télécharger le fichier sera envoyé par e-mail à votre identifiant enregistré "

dans la version 2.1 je ne sais pas comment mettre en file d'attente, mais j'ai trouvé ceci là où ils utilisent " Queued Chunk ", mais je ne sais pas comment l'implémenter.

Alors, des mises à jour à ce sujet?

Alors, des mises à jour à ce sujet?

Si quelqu'un utilise Laravel Excel 3.0+, la solution supérieure ne fonctionnera pas. vous devez donc remplacer buildExcelFile() en utilisant "Exportation en file d'attente" .

Ou j'ai fait autre chose en utilisant le chunking aussi mais en créant mon trait et en utilisant CSV pour faire mon travail et ceci un exemple

les mises à jour ?

À partir de Laravel 6, vous pouvez utiliser LazyCollections pour charger un seul élément à la fois en mémoire. Cela résout le problème de manquer de mémoire.

Il suffit d'étendre la classe DataTable et d'écrire un DataTablesExportHandler adapté.

Découvrez mon essence

Prendre plaisir!

@singhofmarco Pouvez-vous donner l'exemple?

@singhofmarco Je suis d'accord, j'ai lancé un projet v10 l'année dernière qui utilisera LazyCollections mais ne peut pas le poursuivre.

J'ai emprunté une voie différente. J'ai remplacé la fonction csv, en appelant DataTables avec une page de données à chaque fois, ce qui réduit efficacement la taille. En utilisant fputcsv sur les lignes de résultat jusqu'à ce que le fichier soit complet, retournez simplement le contenu du fichier dans une réponse Laravel.

Non seulement la limite de mémoire n'est plus jamais atteinte (jusqu'à ce que le CSV lui-même dépasse la limite de mémoire PHP, une réponse en continu pourrait aider davantage), mais c'est aussi plus de deux fois plus rapide ......

@ameenross si possible pouvez-vous partager votre code s'il vous plaît.

@karmendra Je préfère ne pas le faire, car c'est pour une ancienne version de Yajra Datatables. Mais fondamentalement, ce que je fais, c'est que je fusionne des valeurs de page et de longueur dans la requête, appelez le code qui renvoie normalement une page de données pour AJAX ( $this->ajax()->getData(true)['data'] dans mon cas). J'ai une classe de base pour les tables de données qui étend la classe Yajra Datatable, avec une fonction getCsv (j'ai décidé de ne pas remplacer la fonction CSV après tout, mais ce n'est pas important). Cela va en boucle jusqu'à ce qu'il ne reste plus de pages.

@ameenross Merci qui est utile. Je veux bien essayer.

Laravel Datatable :: v1.5.0
Voici ma solution basée sur le commentaire @TheGeekyM , je la laisse au cas où cela aiderait quelqu'un d'autre.
J'ai créé une classe ChunkedDatatableExportHandler qui implémente FromQuery, puis remplace la méthode buildExcelFile dans mes ServiceDataTables pour l'utiliser.

<?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;
    }
}
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

kamrava picture kamrava  ·  3Commentaires

SGarridoDev picture SGarridoDev  ·  3Commentaires

sangnguyenplus picture sangnguyenplus  ·  3Commentaires

Abdulhmid picture Abdulhmid  ·  3Commentaires

ghost picture ghost  ·  3Commentaires