Есть магазин с большим количеством товаров (более 100000). Нужно в цикле пройти по всем товарам и записать их аттрибуты в текстовый файл (нечто вроде импорта)
Написал скрипт, работающий из командной строки в котором
беру простым SQL запросом из базы данных Магенто список id товаров (порциями по 1000 штук).
А потом иду в цикле по каждой порции и загружаю товар по его id.
foreach ($products as $v){ $product = Mage::getModel('catalog/product')->load($v["product_id"]); $product->clearInstance(); unset($product); }
Методом тыка определил, что если просто иду по циклу без загрузки товара - утечек пямяти нет, все ID товаров перебираются.
Пока не поставил clearInstance и unset, лимит памяти на моем сервере исчерпывался примерно после 11000 товаров.
Поставил очистку - стал слетать по лимиту памяти примерно на 55000 товаров.
Может кто знает, что за фигня, память не чистится.
Версия магенто последняя - 1.7.0.2.
Память может утекать как из-за скрипта, объекты коллекций и базы все равно висят и копятся, так и из-за сборщика мусора PHP.
самое надежное грузить sql прямыми запросами, второе грузить коллекцию с нужными атрибутами и пагером с limit.
Грузить каждый раз создавая модель это не гут, много всего тянется.
Либо, если очень хочется так, то грузить только нужные атрибуты
Проверил ваш вариант с указанием требемых атрибутов - $product-->load($id, array(.....)); - указал price, visibility
Столкнулся с интересным эффектом:
- потребление памяти растет, но гораздо медленней. Если раньше у меня слетало на 55000 товаров, то сейчас прошелся по всем 112000 товаров, причем, запас по памяти остался еще тысяч на 50000 товаров (это примерно, я смотрю по top команде).
НО самое интересное не это. У меня выполняется два прохода по полному списку товаров. Т.е. первый проход у меня выполнился полностью (112000 товаров) и я добрался до второго прохода. Невероятно, но факт - при втором проходе по всем товарам (тот же кусок кода) - потребление памяти абсолютно не увеличивается. Получается, что где-то существует нечто вроде кэша… Вот как бы его найти и вычистить…
Процесс закончился - на втором проходе никакого роста памяти…
Скорее всего, объекты атрибутов и их значений остаются в памяти, они не привязаны к catalog/product поэтому не удаляются вместе с ним.
Почистить надо потрудиться) хотя вроде как смысла нет, сборщик мусора PHP сделает это после выполнения скрипта.
Не извиним))
Мягко говоря fetchItem делает выборку только из таблицы catalog_product_entity и атрибуты не подгружает, то есть для наших целей она не подойдет.
array(33) { ["entity_id"] => string(3) "140" ["entity_type_id"] => string(2) "10" ["attribute_set_id"] => string(2) "58" ["type_id"] => string(6) "simple" ["sku"] => string(7) "2gbdimm" ["created_at"] => string(19) "2008-07-25 00:59:55" ["updated_at"] => string(19) "2008-07-25 02:14:23" ["has_options"] => string(1) "0" ["required_options"] => string(1) "0" ["meta_keyword"] => string(0) "" ["description"] => string(572) "Crucial 2GB PC4200 DDR2 533MHz Memory Crucial Technologies is part of Micron, the largest DRAM manufacturer in the U.S. and one of the largest in the world. Because they actually manufacture memory, they have unparalleled expertise in the upgrade industry. Crucial is the only consumer memory upgrade supplier that is part of a major DRAM manufacturer.
Every single Crucial memory module is tested before it goes out their doors. Crucial chips are individually tested under varying temperatures, voltages, and operational conditions for performance and functionality. " ["short_description"] => string(572) "Crucial 2GB PC4200 DDR2 533MHz Memory Crucial Technologies is part of Micron, the largest DRAM manufacturer in the U.S. and one of the largest in the world. Because they actually manufacture memory, they have unparalleled expertise in the upgrade industry. Crucial is the only consumer memory upgrade supplier that is part of a major DRAM manufacturer.
Дело в том, что при использовании fetchItem все равно нужно будет выполнять операцию загрузки товара (load), так как выше уже отметили, что необходимые атрибуты не грузятся по умолчанию.
А при загрузке товара все равно происходит утечка, я уже приводид данные выше.
[Wed May 22 12:56:26 2013] [error] [client 94.70.241.39] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 74 bytes) in /var/www/mage_store/app/code/core/Mage/Sitemap/Model/Resource/Catalog/Product.php on line 186, referer: http://www.domain.com/index.php/admin/sitemap/index/key/1c0fc48fa96dec310d1c9f71796ad59e/
В магазине более 100000 товаров. Памяти не хватает именно когда пытается добавить товары в sitemap.xml (я проверил, если закомментарить выдачу товаров - все заканчивается нормально).
Админ панель умирает. 512 мегабайт памяти для PHP не спасает. Разработчики магенто вообще в курсе того, что есть такая проблема?
Там же элементарный перебор коллекции всех товаров.
Я понимаю, что sitemap.xml имеет свои ограничения (не более 50000 итемов и не более 10 мегабайтов), но я очень сомневаюсь, что и 50000 товаров в один файл выдаст.
unset() делает то, что его имя говорит - сбросить переменную. Это не приведет к немедленному освобождению памяти. Сборщик мусора PHP будет делать это, когда это увидеть))
Если вы делаете все, что $ = NULL; то вы переписывания данных переменной. Вы можете получить памяти освободил / сократился быстрее, но он может украсть циклов центрального процессора от кода, который действительно нуждается в них раньше, в результате чего больше общего времени выполнения.
т.е. unset не освобождает память сразу, а null может освободить.
можно поэкспериментировать + 256 маловато для 100000 товаров, вроде.
Я экспорт сделал через связку shell-script+php_cli по интервалам id товаров. (1-5000,5001-10000,....)
Больше не влезало. Так там я уверен был, что каждый раз память с чистого листа.
А здесь скорее всего никак не победить без полного переписывания начинки Sitemap.php.
Там еще и AW_Blog торчит, который Sitemap.php переопределяет.
А потом надо решать проблему 50000 линков в одном файле sitemap.xml и макс размер файла не более 10Мбайт.
Предложил клиенту расширение от MageWorx, там вроде бы уже все предусмотрели. Пусть думает.