Синхронизация запасов Magento с использованием большого объема памяти - какие у меня есть варианты, чтобы уменьшить использование памяти?
У меня есть файл примерно из 100 000 артикулов, количество которых необходимо обновить в Magento.
По соображениям скорости я делаю несколько вещей:
1. Я создаю массив артикулов, идентификаторов продуктов и артикулов, чтобы мне не нужно было звонить для каждого продукта, чтобы найти идентификатор продукта по коду артикула или получить текущее количество.
2. Текущее количество сверху затем сравнивается с количеством в файле. Если это то же самое, то обновление не происходит.
3. Мы используем плагин для нескольких складов, и поэтому я также сохраняю список cataloginventory_stock_item item_id
, чтобы я мог просто вызвать модель и обновить ее.
Моя проблема в том, что процесс использует почти 2 ГБ памяти. Я не совсем понимаю, почему. Файл, который я читаю построчно, составляет всего 5 МБ. Я запускаю следующие функции и помещаю результаты в массив, в котором должна использоваться память.
protected function _getStockItemsAsArray() {
$stockCollection = Mage::getModel("cataloginventory/stock_item")->getCollection();
$out = [];
foreach ($stockCollection as $stock) {
$product_id = $stock->getData("product_id");
$warehouse_id = $stock->getData("stock_id");
$stock_item_id = $stock->getData("item_id");
$qty = $stock->getData("qty");
$is_in_stock = $stock->getData("is_in_stock");
$out[$product_id][$warehouse_id]["stock_item_id"] = $stock_item_id;
$out[$product_id][$warehouse_id]["qty"] = $qty;
$out[$product_id][$warehouse_id]["is_in_stock"] = $is_in_stock;
}
return $out;
}
protected function _getCurrentStockAsArray() {
$resource = Mage::getSingleton("core/resource");
$readConnection = $resource->getConnection("core_read");
$query = "
SELECT
p.sku,
p.type_id,
w.stock_id,
SUM(IFNULL(pe.qty,0)) pending_qty,
SUM(s.qty) on_hand_qty
FROM
" . $resource->getTableName("catalog_product_entity") . " p
CROSS JOIN
" . $resource->getTableName("cataloginventory_stock") . " w
INNER JOIN
" . $resource->getTableName("cataloginventory_stock_item") . " s on
s.product_id = p.entity_id
LEFT OUTER JOIN
(
SELECT
oi.product_id,
oi.stock_id,
IFNULL(SUM(qty_ordered),0) qty
FROM
" . $resource->getTableName("sales_flat_order_item") . " oi
INNER JOIN
" . $resource->getTableName("sales_flat_order") . " o ON
oi.order_id = o.entity_id
WHERE
o.tigers_export_status IN('Incomplete', 'Failed', 'Pending', 'Exporting')
AND o.status NOT IN('canceled', 'closed')
GROUP BY
oi.product_id,
oi.stock_id
) pe ON
pe.product_id = p.entity_id
and pe.stock_id = w.stock_id
WHERE
p.sku IS NOT NULL
OR p.sku != ''
GROUP BY
p.sku,
p.type_id,
w.stock_id
";
$data = $readConnection->fetchAll($query);
$out = [];
foreach( $data as $key => $value ) {
$out[$value["sku"]][$value["stock_id"]]["on_hand_qty"] = (int)$value["on_hand_qty"];
$out[$value["sku"]][$value["stock_id"]]["pending_qty"] = (int)$value["pending_qty"];
$out[$value["sku"]][$value["stock_id"]]["type_id"] = (int)$value["type_id"];
}
return $out;
}
protected function _getSkuToProductIDAsArray() {
$resource = Mage::getSingleton("core/resource");
$readConnection = $resource->getConnection("core_read");
$query = "
SELECT
sku,
entity_id
FROM
" . $resource->getTableName("catalog_product_entity") . "
WHERE
sku IS NOT NULL
";
$data = $readConnection->fetchAll($query);
$out = [];
foreach( $data as $key => $value ) {
$out[$value["sku"]] = (int)$value["entity_id"];
}
return $out;
}
Какие еще варианты доступны для использования меньше памяти, но все еще есть аналогичная производительность?
1 answers
Использование метода адаптера базы данных fetchAll()
для извлечения больших наборов результатов, безусловно, вызовет большой спрос на систему и ресурсы.
Ваш код может выполняться очень долго, и PHP, вероятно, не хватит памяти, если вы извлекаете большой объем данных.
Вы можете исправить это неэффективное использование памяти, заменив:
$data = $readConnection->fetchAll($query);
$out = [];
foreach( $data as $key => $value ) {
Автор:
$data = $readConnection->query($query);
$out = [];
while ($value = $data->fetch()) {
Таким образом, каждая строка базы данных извлекается отдельно с использованием метода fetch()
для сокращения ресурсов потребление.
Сервер базы данных выполнит только один запрос, и буфер базы данных будет использоваться для извлечения записей по одной.