Синхронизация запасов 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;
}

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

Author: Raphael at Digital Pianism, 2016-04-20

1 answers

Использование метода адаптера базы данных fetchAll() для извлечения больших наборов результатов, безусловно, вызовет большой спрос на систему и ресурсы.

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

Вы можете исправить это неэффективное использование памяти, заменив:

$data = $readConnection->fetchAll($query);
$out = [];
foreach( $data as $key => $value ) {

Автор:

$data = $readConnection->query($query);
$out = [];
while ($value = $data->fetch()) {

Таким образом, каждая строка базы данных извлекается отдельно с использованием метода fetch() для сокращения ресурсов потребление.

Сервер базы данных выполнит только один запрос, и буфер базы данных будет использоваться для извлечения записей по одной.

 1
Author: Raphael at Digital Pianism, 2016-04-20 11:23:40