Magento: A maneira mais rápida de atualizar um atributo do produto

15

Estou procurando o método mais rápido e confiável para atualização de atributos em massa. Abaixo estão os métodos que eu conheço, mas não sei com qual devo ir.

$store_id = 0;
Mage::getSingleton('catalog/product_action')->updateAttributes(
    array($product_id),
    array('attribute_code' => $attribute_code),
    $store_id
);

ou

$product->setData($attribute_code, 1234); 
$product->getResource()->saveAttribute($product, $attribute_code); 
Deepak Mallah
fonte

Respostas:

31

A maneira mais rápida é fazer seleções diretas e inserções / atualizações no banco de dados, mas isso não é o mais seguro. Você pode facilmente quebrar coisas.

Eu uso a Mage::getSingleton('catalog/product_action')->updateAttributes(...)abordagem.
É rápido, você pode usá-lo para atualizar em massa os atributos do produto, pode atualizar um valor de atributo para uma loja específica.
Eu acho que cobre a maioria dos casos necessários.

Marius
fonte
graças Marius eu estava esperando sua resposta, btw seu módulo criador último é Kool
Deepak Mallah
11
na verdade, não é a escolha mais rápida ... verifique minha resposta abaixo
Fev
@Fra Como é o seu método mais rápido? Isso envolve load. que tudo menos rápido. Por exemplo, no método 2, a primeira linha com a carga do produto é inútil. Você não está usando em $productlugar algum.
Marius
@Fra. Quando você rejeita a resposta de alguém, é uma boa coisa indicar uma razão. O que há de errado com a minha resposta?
Marius
11
Eu poderia dizer a mesma coisa para a sua resposta ... não é o caminho mais rápido. consultas SQL diretas são a maneira mais rápida. Não acho que sua razão seja suficiente para fazer uma votação negativa. Mas você tem direito à sua opinião.
Marius
27

Na verdade, existem três maneiras de atualizar um atributo em um produto sem salvar o produto completo. Dependendo do código / requisitos, um pode ser mais rápido que o outro.

Método 1:

$product = Mage::getModel('catalog/product')->load($product_id);
$resource = $product->getResource();

$product->setData($attribue_code, $value);
$resource->saveAttribute($product, $attribute_code);

Método 2:

$updater = Mage::getSingleton('catalog/product_action');
$updater->updateAttributes(array($product_id), array( $attribute_code => $value), 0);

Método 3: (mais rápido)

 $update_resource = Mage::getResourceSingleton('catalog/product_action');
 $update_resource->updateAttributes(array($product_id), array( $attribute_code => $value), 0);

Todos os métodos acima são muito mais rápidos que salvam todo o produto, de qualquer maneira, existem algumas diferenças importantes de desempenho:

Method 1:

  • é o mais rápido, mas é necessário que você carregue o produto.
  • não aciona o evento reindex (é por isso que é mais rápido)
  • funciona no frontend

Method 2:

  • permite atualizar produtos em massa
    (você pode transmitir vários produtos e vários atributos)
  • desencadeia o evento de ação em massa e a rédea dependente relativa
  • não funciona no frontend

Method 3:

  • é como o método 2, mas não chama nenhum outro observador / indexador
    (portanto, é uma abordagem mista entre os métodos 1 e 2)

O método 3 é o mais flexível de qualquer maneira, você precisará reindexar esses produtos / atributos manualmente. (para atualizá-los no front-end)
Pode ser útil se você deseja atualizar muitos produtos rapidamente e depois chamar a reindexação no final.
(se você usar o método 2, uma reindexação para cada produto será chamada após a atualização e essas várias chamadas tornarão o processo lento)

Para reindexar manualmente um único produto, consulte as funções fornecidas pelo Mage_Catalog_Model_Product_Flat_Indexer , como:

  • updateAttribute($attributeCode, $store = null, $productIds = null)
  • updateProduct($productIds, $store = null)
  • ...
Fra
fonte
4
seria sempre melhor comentar downvote ...
Fra
Apenas uma pequena nota, o valor R $ deve ser um código o valor (inteiro), não o 'textuais' valor que você vê na sua interface
Ali Alwash
hmmm interessante. O método 2 parece ótimo, mas você não tem controle sobre o "feedback" do que teve sucesso, o que não teve? O método 1 também é bom. Mas quando terminar de atualizar meu loop sobre os dados: posso chutar a reindex manualmente talvez para resolver isso para IDs de produtos específicos?
snh_nl
Estranho. usando o método 2. Estou recebendo um filtro de erro desconhecido pela coluna `` `Exceção capturada: SQLSTATE [42S22]: Coluna não encontrada: 1054 Coluna desconhecida 'catalog_product_entity.value_id' na 'lista de campos', a consulta foi: SELECT catalog_product_entity. value_idFROM catalog_product_entityWHERE (entity_type_id = 4 AND attribute_id = '68 'AND entity_id = '29') `` `não esperava isso. Rodando em 1.9.3.2
snh_nl
11
Economizou-me horas de trabalho.
dipole_moment
3

Atualizar

Estou procurando o método mais rápido e confiável para atualização de atributos em massa

"Atualização de atributos em massa" para atributos ou produtos?

Pense em atualizar vários atributos já está respondido, mas para produtos isso pode ser útil ...

Se você deseja atualizar produtos da coleção, não deve fazer isso ...

foreach ($collection as $product) {
    $product->setSomeData(...);
    # not here
    $product->save();
}

Isso enviará eventos, reconstruirá pré-requisitos e índices. Com isso, nenhum evento (e outras coisas) é ignorado e é muito mais rápido.

foreach ($collection as $product) {
    $product->setSomeData(...);
}
$collection->save();

Para evitar atualizações de pré-requisitos, você pode adicionar ...

$product->setIsMassupdate(true);

Para desativar / ativar o reindex em tempo real, dê uma olhada neste ... https://github.com/Flagbit/Magento-ChangeAttributeSet/commit/676f3af77fec880bc64333403675d183e8639fae

/**
 * Set indexer modes to manual
 */
private function _storeRealtimeIndexer()
{
    $collection = Mage::getSingleton('index/indexer')->getProcessesCollection();
    foreach ($collection as $process) {
        if($process->getMode() != Mage_Index_Model_Process::MODE_MANUAL){
            $this->_index[] = $process->getIndexerCode();
            $process->setData('mode', Mage_Index_Model_Process::MODE_MANUAL)->save();
        }
    }

}
/**
 * Restore indexer modes to realtime an reindex product data
 */
private function _restoreRealtimeIndexer()
{
    $reindexCodes = array(
        'catalog_product_attribute',
        'catalog_product_flat'
    );
    $indexer = Mage::getSingleton('index/indexer');
    foreach ($this->_index as $code) {
        $process = $indexer->getProcessByCode($code);
        if (in_array($code, $reindexCodes)) {
            $process->reindexAll();
        }
        $process->setData('mode', Mage_Index_Model_Process::MODE_REAL_TIME)->save();
    }
}

E também liberar o cache antes que a atualização em massa (produto) possa aumentar o desempenho ...

Mage::app()->getCacheInstance()->flush();

Alguns números de depuração aqui: https://github.com/Flagbit/Magento-ChangeAttributeSet/issues/16


Mage::getSingleton('catalog/product_action')->updateAttributes(...) parece não ser o método mais rápido ... pelo menos não com a configuração do mutlistore e as tabelas planas ativadas ...

  • saveAttribute()

    $product = Mage::getModel('catalog/product')->load($productId);
    $resource = $product->getResource();
    $product->setData($attributeCode, $attributeValue);
    $resource->saveAttribute($product, $attributeCode);
    • Total Incl. Tempo de parede (microsseguro): 437.787 microssegundos
    • Total Incl. CPU (microssegundos): 423.600 microssegundos
    • Total Incl. MemUse (bytes): 4.433.848 bytes
    • Total Incl. PeakMemUse (bytes): 4.395.128 bytes
    • Número de chamadas de função: 25.711
  • updateAttributes()

    Mage::getSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array($attributeCode => $attributeValue),
        $storeId
    );
    • Total Incl. Tempo de parede (microsseguro): 3.676.950 microssegundos
    • Total Incl. CPU (microssegundos): 3.122.064 microssegundos
    • Total Incl. MemUse (bytes): 8.174.792 bytes
    • Total Incl. PeakMemUse (bytes): 8.199.192 bytes
    • Número de chamadas de função: 150,132
  • updateAttributes() (recurso singleton)

    Mage::getResourceSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array( $attributeCode => $attributeValue),
        $storeId
    );
    • Total Incl. Tempo de parede (microsseguro): 94.155 microssegundos
    • Total Incl. CPU (microssegundos): 48.568 microssegundos
    • Total Incl. MemUse (bytes): 1.426.304 bytes
    • Total Incl. PeakMemUse (bytes): 1.370.456 bytes
    • Número de chamadas de função: 2,221
sv3n
fonte
você pode revisar minha resposta para entender por que essas funções levam tempos diferentes ...
Fra
Para dados suspensos, updateAttributes() (resource singleton)leva o valor real de administrador? ou o ID do elemento suspenso? (de alguma forma nós sempre obter nenhum valor valor / vazio usando este método ou seja, nada selecionado
snh_nl
@snh_nl, você precisa usar o ID - vírgula separada para atributos de seleção múltipla.
sv3n