Самый быстрый способ проверить, существуют ли продукты


У меня есть внешний файл, содержащий сведения о продукте, я просматриваю этот файл, и для каждого продукта в указанном файле я должен проверить, существует ли продукт уже в magento.

Значение для оценки того, существует ли продукт уже, - это имя атрибута и его значение.

Поэтому я проверяю это с помощью (для каждого продукта)

$collection = Mage::getModel('catalog/product')
                ->getCollection()
                ->addAttributeToSelect('sku')
                ->addAttributeToSelect("$supplier_name")
                ->addAttributeToSelect('production_nr')
                ->addAttributeToSelect('sku_supplier')
                ->addAttributeToFilter($supplier_name,array('eq' => $suppliers_product_nr));

Сам по себе этот выбор, похоже, не занимает много времени:

            echo 'check: ',round(microtime(true) - $time, 2) , "s<br/>\n";

Сообщает 0.00 с,

Однако, чтобы проверить, является ли это пустая коллекция (т.е. продукт существует в моей базе данных magento) занимает около 0,34-0,40 с

$collection->getSize()

Учитывая, что мне нужно проверить несколько сотен тысяч продуктов. Это быстро сложится. Очень быстро. Я надеялся на что-то более близкое к 0,01 или ниже по времени.

Поэтому я ищу самый быстрый способ проверить, существует ли продукт. У меня довольно много свободы в том, как изменять и реализовывать код, поэтому, если есть совершенно другой способ решения этой проблемы Я хотел бы услышать об этом.


Обновление:

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

Это намного быстрее, но я боюсь, что это скажется на накладных расходах (в первую очередь на ОЗУ или процессоре), как только количество возвращаемых продуктов станет слишком большим (у нас около 40.000 продуктов в нашей установке magento)

Author: Kamlesh Jha, 2017-03-16

3 answers

Насколько мне известно, лучшим решением было бы getAllIds().

Объяснение

$collection = Mage::getModel('catalog/product')
                ->getCollection()
                ->addAttributeToSelect('sku')
                ->addAttributeToSelect("$supplier_name")
                ->addAttributeToSelect('production_nr')
                ->addAttributeToSelect('sku_supplier')
                ->addAttributeToFilter($supplier_name,array('eq' => $suppliers_product_nr));

Это не займет много времени, так как это просто подготовка запроса на сбор данных. Этот запрос будет фактически выполнен только тогда, когда коллекция будет загружена через вызов load() или через цикл foreach() или через вызов count() и т.д.

Здесь вы можете проверить статус количества собранных данных многими способами. Я перечисляю их в соответствии с их наилучшей производительностью (производительность снижается во время перехода вниз).

  • $collection->getAllIds() - Лучший вариант
  • $collection->getSize()
  • count($collection)
  • $collection->count() - Наименьший вариант

Почему Такой Порядок?

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

count($collection) не имеют большой разницы с приведенным выше.

getSize() определяет в Varien_Data_Collection_Db, и это позволяет избежать загрузки коллекции. Это большое преимущество сюда. Это даст вам хорошую производительность при использовании его для проверки. Смотрите ответ от Мариуса для получения более подробной информации.

getAllIds() это лучший выбор. Этот метод доступен в Mage_Eav_Model_Entity_Collection_Abstract, и он имеет очень тонкое отличие от getSize() в определении, и это делает этот лучший выбор.

getAllIds() внутренне вызывает getAllIdsSql() и смотрите определение здесь:

public function getAllIdsSql()
{
    $idsSelect = clone $this->getSelect();
    $idsSelect->reset(Zend_Db_Select::ORDER);
    $idsSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
    $idsSelect->reset(Zend_Db_Select::COLUMNS);
    $idsSelect->reset(Zend_Db_Select::GROUP);
    $idsSelect->columns('e.'.$this->getEntity()->getIdFieldName());

    return $idsSelect;
}

Здесь $idsSelect->columns('e.'.$this->getEntity()->getIdFieldName()); то, что делает этот метод лучшим из всех доступных методов. На самом деле, эта строка отсутствующий в getSize().

 3
Author: Rajeev K Tomy, 2020-06-15 08:30:17

Самый быстрый способ для одного вызова - использовать getIdBySku из catalog/product:

if (Mage::getSingleton('catalog/product')->getIdBySku('yoursku')) {
  // Product exists
} else {
  // Product does not exist
}

Обратите внимание на getSingleton вместо getModel для этого использования!

Альтернатива:

Если вам нужно прочитать их все сразу, вы можете использовать getAllIds() из коллекции.

 3
Author: Phoenix128_RiccardoT, 2017-03-17 11:41:43

Как упоминалось ниже Радживом К Томи, скорость запроса с использованием метода getAllIds() кажется самой быстрой в magento. Но вы также можете получить необходимые значения атрибутов (например, "production_nr" или "sku_supplier") без загрузки коллекции. Этот метод немного медленнее, чем getAllIds().

//addAttributeToSelect use only for EAV attributes
$collection = Mage::getModel('catalog/product')
    ->getCollection()
    ->addAttributeToSelect('meta_title', true) 
    ->addAttributeToSelect('meta_description', true)
    ->addAttributeToFilter(
        'name',
        array('like' => '%a%')
    );
//columns() use only for static attributes (product entity fields)
$collection->getSelect()->reset('columns')->columns(['entity_id', 'sku']);

/** @var Varien_Db_Select $select */
$select = $collection->getSelect();

/** @var Mage_Core_Model_Resource $res */
$res = Mage::getSingleton('core/resource');

/** @var Magento_Db_Adapter_Pdo_Mysql $conn */
$conn = $res->getConnection('core_write');
$res = $conn->fetchAll($select, Zend_Db::FETCH_ASSOC);

P.S. Не добавляйте addAttributeToSelect("имя") в коллекцию, если вы используете атрибут "имя" для метода фильтрации.
P.S.2 Смотрите мой вопрос/ответ о быстром получении исходных данных о продукте без загрузки коллекции здесь

 1
Author: sergei.sss, 2017-04-13 12:55:02