Один раз сценарий для установки пользовательского атрибута для ~ 1M клиентов - утечка памяти
-
28-09-2020 - |
Вопрос
Я пытаюсь запустить одноразовый скрипт (в пользовательском модульном обновлении), чтобы установить новый атрибут
У меня есть этот скрипт:
$users = mage::getModel('customer/customer')->getCollection()
->addAttributeToSelect('last_order_date');
foreach ($users as $user){
$lastDate = $user->getData('last_order_date');
if(empty($lastDate)){
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFilter('customer_id', $user->getId())
->setOrder('created_at', Varien_Data_Collection_Db::SORT_ORDER_DESC)
;
$numberOfOrders = $orderCollection->count();
if($numberOfOrders!=0){
$newestOrder = $orderCollection->getFirstItem();
$lastOrderDate = $newestOrder->getCreatedAt();
$user->setData('last_order_date', $lastOrderDate);
$user->save();
}
}
}
.
Но это вызывает утечку памяти:
Фатальная ошибка: Разрешено размер памяти 1073741824 байта исчерпаны (пробовал выделить 32 байта) в [..] / Web-root / lib / zend / db / адаптер / pdo / allow.php на линии 292
Что я понимаю, связано с петлими вызовами для Mage::getModel('sales/order')
.
Как мне добиться этого без повторных звонков?
Решение
.
require_once 'app/Mage.php';
Mage::app();
$current_page = isset($_GET['current_page']) ? 1 : $_GET['current_page'];
$users = mage::getModel('customer/customer')->getCollection()
->addAttributeToSelect('last_order_date')
->setPageSize(100)
->setCurPage($current_page);
if($users->count() == 0){
die('done');
}
foreach ($users as $user){
$lastDate = $user->getData('last_order_date');
if(empty($lastDate)){
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFilter('customer_id', $user->getId())
->setOrder('created_at', Varien_Data_Collection_Db::SORT_ORDER_DESC)
;
$numberOfOrders = $orderCollection->count();
if($numberOfOrders!=0){
$newestOrder = $orderCollection->getFirstItem();
$lastOrderDate = $newestOrder->getCreatedAt();
$user->setData('last_order_date', $lastOrderDate);
$user->save();
}
}
}
$current_page++;
//go to next page
$redirect_url = "http://yoururlhere/set_last_order_date.php?current_page=" . $current_page;
?>
<script type="text/javascript">
setTimeout("location.href = '<?php echo $redirect_url;?>';", 50);
</script>
Другие советы
Добавлено в Gurutheme Ответить Огромный производительный сервер - использовать saveAttribute
вместо save
Так что замените следующее
$user->setData('last_order_date', $lastOrderDate);
$user->save();
.
с:
$user->setData('last_order_date', $lastOrderDate);
$user->getResource()->saveAttribute($user,'last_order_date');
.
Таким образом, вы будете сохранять только один атрибут вместо того, чтобы сохранить каждый атрибут модели клиента.