Laravel-datatables: サーバー側のエクスポート200000レコード

作成日 2018年03月31日  ·  19コメント  ·  ソース: yajra/laravel-datatables

問題または機能のリクエストの概要

200000がデータのエクスポート方法を記録する場合。 データをエクスポートすると、 「許可されたメモリサイズ134217728バイトが使い果たされました」という例外がスローされました。

yajra / datatableに大量のデータをエクスポートする他のオプションは何ですか。

大量のデータをエクスポートする別の方法を提供してください。

サーバー上のRAMの量は限られています。

問題のコードスニペット

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

システムの詳細

  • オペレーティングシステム:Ubuntu 16.04
  • PHPバージョン:7.0.0
  • Laravelバージョン:5.5
  • Laravel-Datatablesバージョン:8.0
  • Laravel-Datatablesボタンバージョン:3.1
performance question

全てのコメント19件

この一括リクエストを処理するには、独自のExcelファイルビルダーを実装する必要があります。 ServiceDataTableクラスでは、 protected function buildExcelFile()メソッドをオーバーライドして、チャンクなどを実行できます。詳細については、laravel-excelのドキュメントを参照してください。

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

次のコード作成例外だと思います
$this->getDataForExport();
サーバー側のeditColumn()定義または使用されると、例外が発生します
200000レコードがあります。
処理せずに、またはより多くのメモリを割り当てずにデータを取得する他の方法はありますか?
私は次のリンクを持っていますが、yajra yajra / laravel-datatables-buttons:^ 3.1はまだLaravel / Excelをサポートしていません:3.0
https://laravel-excel.maatwebsite.nl/docs/3.0/export/queued

クエリから直接エクスポートする方法または雄弁な方法があるはずです。

私はPostmanを使用してその操作を模倣していますが、

134217728バイトの許容メモリサイズが使い果たされました

例外がスローされました。 htmlの生成に使用した行がありません。rawColumns()を使用してhtmlをエスケープします。クエリには、phpmyadminで0.420ミリ秒かかり、最初は1.4秒かかります。

これをキューに入れることができれば、サーバー上のフォルダーに保存して、ダウンロードするためのリンクをユーザーに提供することもできるはずです。

ご返信ありがとうございます。

JQueryDatatableまたはyajradatatableで使用しており、サーバー側からエクスポートしたいと考えています。

サーバー上のフォルダに保存することは不可能だと思います。問題を引き起こす多くの問題があります。

データのストリーミングが必要です。

応答のデータ量は20MB以上です。

私の要件も同様ですが、ファイルをサーバー(またはS3)に保存し、アプリケーションダッシュボードまたは電子メールでダウンロードするためのリンクを提供したいと思います。 私はこれを行う可能性を見ています、私がここで更新する何かを見つけたら。

大量のRAMを消費するサーバーサイド処理に問題があり、デフォルトのスクリプトメモリ割り当てサイズは60MBです。
php.iniのmemory_limitを見てください
実行時間制限max_execution_timeは60です。
値を増やした後、サーバーサイドエクスポートを使用してリクエストを行うことができました。

ダウンロードではなくファイルを保存するようにExcel関数を変更しました。これは、ファイルをstorage / exports /フォルダーに保存することです。

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

現在、開発環境に大量のデータがありません。セットアップで上記の変更を加えて、メモリの上限に達することなくそのフォルダーにExcelを作成できるかどうかを確認できますか?

もう1つ注意すべき点は、Laravel 5.1を使用しているため、maatwebsite / excelバージョン2.1です。

私が本当にやりたいのは、代わりにこれをキューに入れて、レポートの作成が進行中であるというメッセージとともにページに戻り、ファイルをダウンロードするためのリンクが登録済みのIDに電子メールで送信されることです。」

2.1バージョンでは、キューに入れる方法がわかりませんが、「キューに入れられたチャンク」を使用している場所でこれを見つけましたが、これを実装する方法がわかりません。

それで、これについての更新はありますか?

それで、これについての更新はありますか?

Laravel Excel 3.0以降を使用している場合、上位のソリューションは機能しません。 したがって、 「キューに入れられたエクスポート」を使用してbuildExcelFile()をオーバーライドする必要があります。

または、チャンクを使用して別のことを行いましたが、トレイトを作成し、CSVを使用して作業を行いました。これは例です。

更新はありますか?

Laravel 6以降、LazyCollectionsを使用して、メモリに一度に1つのアイテムのみをロードできます。 これにより、メモリ不足の問題が修正されます。

DataTableクラスを拡張し、適合したDataTablesExportHandlerを作成するだけで済みます。

私の要点をチェックしてください

楽しい!

@singhofmarco例を挙げていただけますか?

@singhofmarco同意します。昨年、LazyCollectionsを利用するv10プロジェクトを開始しましたが、ATMで続行することはできません。

私は別のルートに行きました。 csv関数をオーバーライドし、毎回1ページのデータでDataTablesを呼び出し、効果的にチャンク化しました。 ファイルが完了するまで結果行でfputcsvを使用してから、Laravelレスポンスでファイルの内容を返します。

メモリ制限に到達しなくなっただけでなく(CSV自体がPHPメモリ制限を超えるまで、ストリーミング応答がさらに役立つ可能性があります)、2倍以上の速度もあります......

@ameenross可能であれば、コードを共有してください。

@karmendra古いバージョンのYajraDatatables用なので、私はむしろし$this->ajax()->getData(true)['data'] )。 Yajra Datatableクラスを拡張するdatatablesの基本クラスがあり、関数getCsvがあります(結局、CSV関数をオーバーライドしないことにしましたが、それは重要ではありません)。 これは、ページがなくなるまでループします。

@ameenrossありがとうございます。 これを試してみます。

Laravel Datatable :: v1.5.0
これが@TheGeekyMコメントに基づく私の解決策です。他の誰かに役立つ場合に備えて残しておきます。
FromQueryを実装するChunkedDatatableExportHandlerクラスを作成し、ServiceDataTablesのbuildExcelFileメソッドをオーバーライドして使用しました。

<?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;
    }
}
このページは役に立ちましたか?
0 / 5 - 0 評価