Phpexcel не хватает памяти

Обновлено: 04.07.2024

Я пытаюсь пройти через документ Excel 3mb, чтобы получить все данные, которые мне нужно будет вставить в базу данных. Рабочий лист, который я использую, имеет 6500 строк, но может измениться в будущем. Я заметил, что, несмотря на то, что я использую рекомендуемые методы экономии памяти, он все же отключается

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

У библиотеки PHP excel как известно, есть эти проблемы с памятью, у меня также была проблема с этим. Для меня это был совет (из приведенной выше ссылки, попробуйте, есть хорошие советы, как уменьшить использование памяти):

Но в любом случае требования к памяти большие, потому что они выделяют много памяти для каждой ячейки (для форматирования и т.д., даже если это не нужно). Боюсь, что мы беспомощны, пока не выпустили новую версию библиотеки.

Хорошо, все знают, что trwtf - это Excel, поэтому могу ли я спросить, возможно ли вам преобразовать это в CSV?

У меня есть свои собственные CSV для табличных функций в PHP, которые были использованы для импорта очень больших файлов, CSV, как правило, намного легче обрабатывать, а также гораздо менее подвержен случайным проблемам библиотеки.

Если вам действительно нужно это для одноразового процесса или вы можете легко перейти от XLS к CSV, сделайте это, так как это упростит вашу жизнь (как каждый раз вы будете придерживаться более простых, более стандартных альтернатив;)).

Итак, для API, который будет транслировать oh-so-evil и ужасный формат XLS, вы можете использовать один из следующих o/s-преобразователей - я бы рекомендовал python каждый раз, но эй, ваш выбор:

В принципе, идея та же, вы используете внешний инструмент, чтобы получить полезный формат файла, а затем оттуда.

хотя я могу увеличить лимит памяти в конфигурации, но будет здорово увидеть, есть ли какие-либо альтернативы для исправления этот.

размер файла не является хорошей мерой для файлов книги при работе с PHPExcel. Количество строк и столбцов (т. е. ячеек) является более важным.

сам код PHPExcel имеет размер от 10 до 25 МБ, в зависимости от того, к каким компонентам осуществляется доступ.

в настоящее время каждая ячейка в книге занимает в среднем 1k памяти (без кэширования) или 1.6 k на 64-битном PHP - я буду считать 32-битный PHP на данный момент-так (например) рабочий лист 8000 строк с 31 столбец (248,000 ячеек) будет около 242 МБ. При кэшировании ячеек (например, php://temp или DiskISAM) это может быть уменьшено примерно до трети, поэтому для 8000 строк по 31 столбцу потребуется около 80 МБ.

есть несколько вариантов, которые помогут вам уменьшить использование памяти:

вы используете кэширование ячеек с помощью PHPExcel?

Если вам нужно только получить доступ к данных в таблицах, и не нужен доступ к ячейки, то вы можете отключить чтение информации о форматировании из книги:

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

если вы хотите читать только определенные ячейки в листах, вы можете добавить фильтр:

все эти методы могут значительно уменьшить требования к памяти.

PHPExcel известен утечками памяти. Я советую вам использовать следующее, что нужно часть памяти, которую использует PHPExcel.:

только потому, что файл данных только X байт, не означает, что он использует X байт ОЗУ. Например, только 4K данных в массиве $_SESSION использует 64K ОЗУ при загрузке. Все зависит от того, что код делает с этими данными. Правильный ответ-увеличить объем ОЗУ.

также, если это XLSX-файл, они являются ZIP-документами XML. Текстовые файлы zip вверх гораздо плотнее, чем 1/2, так что ваш 350K XLSX файл легко 1 МБ файл Excel.

Xdebug является профилировщиком / отладчиком для php и может помочь вам отслеживать использование памяти и функциональные вызовы, чтобы выяснить, где проблема. И его легко установить, большинство дистрибутивов linux имеют его в репозитории, "yum install xdebug", "apt-get install xdebug".

одна вещь, которую вы должны отметить, тоже пустые ячейки.

У меня была такая же проблема, только 800 строк данных и скрипт даже не смог прочитать. Как тайм-ауты, так и ошибки из памяти, когда либо был исправлен.

Что-то @Mark Baker сказал о клетках заставил меня задуматься. Я заметил, что у меня было много пустых ячеек, и копирование только ячеек с данными в новую книгу заставило ее работать за секунду.

надеюсь, это кому-то поможет.

Если вы хотите узнать, вы можете использовать xhprof. Согласно этой ссылке, вы можете отслеживать использование памяти с ним.

У меня проблема с памятью PHPExcel при обработке файла XLS.
Мне приходится работать с довольно большими файлами (от 50 до 200 тыс. Строк и 9-10 столбцов), поэтому мне пришлось использовать ReadFilters для решения проблемы с памятью.

Однако, хотя он довольно хорошо работал с файлами XLSX, используя смесь фоновых процессов и некоторые простые вычисления для размера чанка, я не могу заставить его работать с файлами XLS.

Это кусок кода, где все взрывается:

Сразу после этого я включил следующие строки, чтобы лучше понять, что происходит:

И я думаю, что это указывало на то, где проблема с памятью.
Когда я впервые загрузил оригинальный файл XLS, файл excel-info.txt имел размер 13M.
Затем я открыл файл XLS и сохранил его как XLSX, и повторил процесс, после чего в excel-info.txt было всего 285 Кбайт.

Можно ли как-то изменить эти фильтры для работы с файлами XLS?

Да, и установка предела памяти PHP на более высокое значение не является опцией, но время выполнения не критично.

ADDED

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

Прямо сейчас я использую PHPExcel_CachedObjectStorageFactory :: cache_to_sqlite, и, кажется, этого достаточно, чтобы он работал.

Теперь я использую этот код для отслеживания использования памяти:

С определенным файлом XLS он показывает:

1-я итерация
1- Использование: 4.3859634399414
2- Использование: 34.292671203613
3- Использование: 34.68034362793

2-я итерация
1- Использование: 34.68034362793
2- Использование: 34.68293762207
3- Использование: 34.684982299805

И тот же файл, после сохранения как XLSX:

1-я итерация
1- Использование: 4.2780990600586
2- Использование: 6.9042129516602
3- Использование: 7.2916641235352

2-я итерация
1- Использование: 7.2916641235352
2- Использование: 7.5115432739258
3- Использование: 7.2813568115234

Однако я должен сказать, что после сохранения в формате XLSX размер уменьшается примерно вдвое, поэтому я не могу сказать, является ли это ошибкой или ожидаемым поведением.

Решение

Вы пробовали setReadDataOnly (правда)?

Другие решения

Просто добавьте эту строку (например)

это решит проблему с памятью ..

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

Я этого не понимаю. Таблица XSLX имеет размер около 3 МБ, но даже 1024 МБ оперативной памяти недостаточно для PHPExcel, чтобы загрузить ее в память?

Возможно, я делаю здесь что-то ужасно неправильное:

Описанная выше функция считывает данные из таблицы Excel в массив.

Есть какие-нибудь предложения?

Сначала я разрешил PHP использовать 256 МБ оперативной памяти. Этого было недостаточно. Затем я удвоил сумму, а затем также попробовал 1024 МБ. У него все еще не хватает памяти с этим ошибка:

7 answers

На форуме PHPExcel много написано об использовании памяти PHPExcel; поэтому чтение некоторых из этих предыдущих обсуждений может дать вам несколько идей. PHPExcel содержит представление электронной таблицы "в памяти" и подвержен ограничениям памяти PHP.

Физический размер файла в значительной степени не имеет значения. гораздо важнее знать, сколько ячеек (строк*столбцов на каждом листе) он содержит.

"Эмпирическое правило", которое я всегда используется в среднем около 1 Кб/ячейка, поэтому для рабочей книги с 5 ячейками потребуется 5 ГБ памяти. Однако существует несколько способов уменьшить это требование. Их можно комбинировать в зависимости от того, к какой именно информации вам нужно получить доступ в вашей рабочей книге и что вы хотите с ней сделать.

Если у вас несколько листов, но вам не нужно загружать их все, вы можете ограничить количество листов, которые будет загружать читатель, используя метод setLoadSheetsOnly(). Чтобы загрузить один именованный рабочий лист:

Или вы можете указать несколько листов одним вызовом setLoadSheetsOnly(), передав массив имен:

Если вам нужно получить доступ только к части листа, вы можете определить фильтр чтения, чтобы определить, какие ячейки вы действительно хотите загрузить:

Используя фильтры чтения, вы также можете читать книгу "фрагментами", так что в любой момент времени в памяти будет находиться только один фрагмент:

Если вам не нужно загружать форматирование информация, но только данные рабочего листа, тогда метод setReadDataOnly() укажет читателю только на значения ячеек загрузки, игнорируя любое форматирование ячеек:

Используйте кэширование ячеек. Это метод сокращения объема памяти PHP, который требуется для каждой ячейки, но за счет снижения скорости. Он работает, сохраняя объекты ячеек в сжатом формате или за пределами памяти PHP (например, диск, APC, memcache). но чем больше памяти вы сохраняете, тем медленнее будут выполняться ваши сценарии. Однако вы можете, уменьшите объем памяти, необходимый для каждой ячейки, примерно до 300 байт, поэтому для гипотетических 5 м ячеек потребуется около 1,4 ГБ памяти PHP.

Кэширование ячеек описано в разделе 4.2.1 Документации разработчика

РЕДАКТИРОВАТЬ

Глядя на свой код, вы используете итераторы, которые не особенно эффективны, и создаете массив данных ячеек. Возможно, вы захотите взглянуть на метод toArray(), который уже встроен в PHPExcel и делает это за вас. Также возьмите взгляните на это недавнее обсуждение на SO о новом варианте метода rangeToArray() для построения ассоциативного массива данных строк.

У меня была такая же проблема с памятью с PHPExcel и фактически со всеми другими библиотеками. Чтение данных по частям, как предположил Марк Бейкер, могло бы устранить проблему (кэширование тоже работает), но оказалось, что проблема с памятью стала проблемой времени. Время чтения и записи было экспоненциальным, поэтому для больших электронных таблиц это не подходило.

Надеюсь, это поможет!

Существует множество мер, которые вы можете предпринять, чтобы зарезервировать меньше памяти при работе с PHPExcel. Я рекомендую вам предпринять следующие действия для оптимизации использования памяти, прежде чем изменять лимит памяти вашего сервера в Apache.

Избегайте использования очень больших файлов Exel, помните, что именно размер файла замедляет процесс и приводит к сбою.

Избегайте использования функции getCalculatedValue(); при чтении ячеек.

В моем случае phpexcel всегда перебирал 19999 строк. неважно, сколько строк на самом деле было заполнено. Таким образом, 100 строк данных всегда заканчивались ошибкой памяти.

Возможно, вам просто нужно проверить, пусты ли ячейки в текущей строке, а затем "продолжить", чтобы прервать цикл, который повторяет строки.

Просто перепечатываю свой пост из другой темы. В нем описывается другой подход к созданию или редактированию электронных таблиц Excel на стороне сервера, который следует учитывать. Для большого объема данных я бы не рекомендовал такие инструменты, как PHPExcel или Apachepoi (для Java), из-за их требований к памяти. Существует еще один довольно удобный (хотя, возможно, немного неудобный) способ ввода данных в электронные таблицы. Создание или обновление электронных таблиц Excel на стороне сервера может быть достигнуто таким простым способом Редактирование XML. У вас может быть электронная таблица XLSX, размещенная на сервере, и каждый раз, когда данные собираются из базы данных, вы распаковываете ее с помощью php. Затем вы получаете доступ к определенным XML-файлам, содержащим содержимое листов, которые необходимо ввести, и вставляете данные вручную. После этого вы сжимаете папку с электронными таблицами, чтобы распространить ее как обычный файл XLSX. Весь процесс достаточно быстрый и надежный. Очевидно, что существует несколько проблем и сбоев, связанных с внутренней организацией файла XLSX/Open XML (например. Excel, как правило, хранит все строки в отдельной таблице и использует ссылки на эту таблицу в файлах рабочих листов). Но при вводе только таких данных, как числа и строки, это не так сложно. Если кому-то интересно, я могу предоставить некоторый код.

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

Читайте также: