Laravel-datatables: Экспорт на стороне сервера 200000 записей

Созданный на 31 мар. 2018  ·  19Комментарии  ·  Источник: yajra/laravel-datatables

Краткое изложение проблемы или запроса функции

Когда 200000 записей, как экспортировать данные. Когда я экспортирую данные «Допустимый размер памяти 134217728 байт исчерпан», возникает это исключение.

Какие еще варианты - экспортировать большой объем данных в yajra / datatable.

Укажите другой способ экспорта большого объема данных.

У нас ограниченное количество оперативной памяти на сервере.

Фрагмент кода проблемы

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, мой запрос занимает 0,420 мс в phpmyadmin и сначала 1,4 секунды.

Если мы сможем поместить это в очередь, мы также сможем сохранить его в папке на сервере, а затем предоставить пользователю ссылку для его загрузки.

Спасибо за ответ.

Я использую его в JQuery Datatable или yajra datatable и хочу экспортировать со стороны сервера.

Я думаю, что невозможно сохранить в папку на сервере, есть много проблем, которые могут вызвать проблемы.

Мне нужна потоковая передача данных.

Размер ответных данных составляет 20 МБ или больше.

Мое требование аналогично, но я хотел бы сохранить файл на сервере (или S3) и дать ссылку для его загрузки на панели инструментов моего приложения или по электронной почте. Я вижу возможность сделать это, если найду что-нибудь, я обновлю здесь.

У меня проблема с обработкой на стороне сервера, которая потребляет большое количество оперативной памяти, а размер выделения памяти сценария по умолчанию составляет 60 МБ.
Посмотрите memory_limit в php.ini
Лимит времени выполнения max_execution_time составляет 60.
После увеличения значения вы смогли сделать запрос, используя экспорт на стороне сервера.

Я изменил функцию Excel, чтобы сохранить файл вместо загрузки, он хранит файл в папке storage / exports /.

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

в настоящее время у меня нет большого количества данных в моем окружении разработки, можете ли вы внести указанные выше изменения в свою настройку и посмотреть, сможет ли он создать Excel в этой папке, не затрагивая ограничение памяти?

Также следует отметить, что я использую Laravel 5.1, поэтому maatwebsite / excel версии 2.1

Что я действительно хочу сделать, так это поставить его в очередь и вернуться на страницу с сообщением о том, что отчет создается, а ссылка для загрузки файла будет отправлена ​​по электронной почте на ваш зарегистрированный идентификатор "

в версии 2.1 не знаю, как поставить в очередь, но я обнаружил, что здесь используется « Queued Chunk », но я не уверен, как это реализовать.

Есть новости по этому поводу?

Есть новости по этому поводу?

Если кто-то использует Laravel Excel 3.0+, верхнее решение работать не будет. поэтому вы должны переопределить buildExcelFile() , используя «Экспорт в очереди» .

Или я сделал что-то еще, используя также фрагменты, но создав свой трейт и используя CSV для выполнения своей работы, и это пример

любые обновления ?

Начиная с Laravel 6, вы можете использовать LazyCollections для загрузки в память только одного элемента за раз. Это решает проблему нехватки памяти.

Нужно только расширить класс DataTable и написать адаптированный DataTablesExportHandler.

Проверьте мою суть

Наслаждайтесь!

@singhofmarco Можете подать пример?

@singhofmarco Я согласен, в прошлом году я начал проект v10, который будет использовать LazyCollections, но не может продолжать его.

Я пошел другим путем. Я переопределил функцию csv, каждый раз вызывая DataTables с одной страницей данных, эффективно разбивая их на части. Используя fputcsv в строках результатов до тех пор, пока файл не будет завершен, просто верните содержимое файла в ответе Laravel.

Мало того, что предел памяти больше никогда не достигается (пока сам CSV не превысит предел памяти PHP, тогда потоковый ответ может помочь в дальнейшем), но он также более чем в два раза быстрее ...

@ameenross, если возможно, поделитесь своим кодом, пожалуйста.

@karmendra Я бы не стал, так как это для более старой версии Yajra Datatables. Но в основном то, что я делаю, это объединяю некоторые значения страницы и длины в запросе, вызываю код, который обычно возвращает страницу данных для AJAX (в моем случае $this->ajax()->getData(true)['data'] ). У меня есть базовый класс для таблиц данных, который расширяет класс Yajra Datatable с функцией getCsv (в конце концов, решил не переопределять функцию CSV, но это не важно). Это продолжается до тех пор, пока не закончатся страницы.

@ameenross Спасибо, что помогло. Я попробую.

Laravel Datatable :: v1.5.0
Вот мое решение, основанное на комментарии @TheGeekyM , я оставляю его на случай, если это поможет кому-то другому.
Я создал класс ChunkedDatatableExportHandler, который реализует FromQuery, а затем переопределил метод buildExcelFile в моих таблицах ServiceDataTables, чтобы использовать его.

<?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 рейтинги