Magento: najszybszy sposób na aktualizację atrybutu produktu

15

Szukam najszybszej i niezawodnej metody masowej aktualizacji atrybutów. Poniżej znajdują się metody, o których wiem, ale nie wiem, z którymi powinienem się zdecydować.

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

lub

$product->setData($attribute_code, 1234); 
$product->getResource()->saveAttribute($product, $attribute_code); 
Deepak Mallah
źródło

Odpowiedzi:

31

Najszybszym sposobem jest bezpośrednie zaznaczanie i wstawianie / aktualizacje w bazie danych, ale nie jest to najbezpieczniejsze. Możesz łatwo zepsuć różne rzeczy.

Używam tego Mage::getSingleton('catalog/product_action')->updateAttributes(...)podejścia.
Jest szybki, możesz go użyć do zbiorczej aktualizacji atrybutów produktu, możesz zaktualizować wartość atrybutu dla określonego sklepu.
Myślę, że obejmuje większość potrzebnych spraw.

Marius
źródło
dzięki marius, spodziewałem się twojej odpowiedzi, btw twoim najlepszym twórcą modułów jest kool
Deepak Mallah
1
tak naprawdę to nie jest najszybszy wybór ... sprawdź moją odpowiedź poniżej
Fra
@Fra W jaki sposób Twoja metoda jest szybsza? To dotyczy load. że cokolwiek, ale nie szybko. Na przykład w metodzie 2 pierwszy wiersz z ładowaniem produktu jest bezużyteczny. $productNigdzie nie korzystasz .
Marius
@Fra. Kiedy głosujesz czyjąś odpowiedź, dobrze jest podać powód. Co jest nie tak z moją odpowiedzią?
Marius
1
Mógłbym powiedzieć to samo dla twojej odpowiedzi ... to nie jest najszybszy sposób. Bezpośrednie zapytania SQL są najszybszym sposobem. Nie sądzę, żeby twój powód był wystarczający do przegłosowania. Ale masz prawo do swojej opinii.
Marius
27

W rzeczywistości istnieją 3 sposoby aktualizacji atrybutu produktu bez zapisywania pełnego produktu. W zależności od kodu / wymagań jedno może być szybsze niż drugie.

Metoda 1:

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

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

Metoda 2:

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

Metoda 3: (najszybsza)

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

Wszystkie powyższe metody są znacznie szybsze, co pozwala zaoszczędzić cały produkt, a mimo to istnieją pewne istotne różnice w wydajności:

Method 1:

  • jest najszybszy, ale wymaga załadowania produktu.
  • nie wyzwala zdarzenia reindex (dlatego jest szybszy)
  • to działa w interfejsie użytkownika

Method 2:

  • pozwala na zbiorczą aktualizację produktu
    (można przekazać wiele produktów i wiele atrybutów)
  • wyzwala zdarzenie akcji masowej i względnie zależny reindeks
  • to nie działa w interfejsie użytkownika

Method 3:

  • jest jak metoda 2, ale nie wywołuje żadnego innego obserwatora / indeksatora
    (więc jest to podejście mieszane między metodą 1 i 2)

Metoda 3 jest jednak bardziej elastyczna i tak będziesz musiał ręcznie reindeksować te produkty / atrybuty. (w celu zaktualizowania ich w interfejsie użytkownika)
Może się przydać, jeśli chcesz szybko zaktualizować wiele produktów, a następnie wywołać reindex na końcu.
(jeśli użyjesz metody 2, po aktualizacji wywoływany jest reindeks dla każdego produktu, a wiele wywołań spowalnia cały proces)

Aby ręcznie reindeksować pojedynczy produkt, zobacz funkcje dostarczone przez Mage_Catalog_Model_Product_Flat_Indexer, takie jak:

  • updateAttribute($attributeCode, $store = null, $productIds = null)
  • updateProduct($productIds, $store = null)
  • ...
Fra
źródło
4
zawsze lepiej byłoby skomentować ...
Fra
Tylko mała uwaga, wartość $ powinna być kodem wartości (liczbą całkowitą), a nie wartością „tekstową”
widoczną
hmmm ciekawe. Metoda 2 brzmi świetnie, tylko nie masz kontroli nad „sprzężeniem zwrotnym”, co się udało, a co nie? Metoda 1 jest również dobra. Ale kiedy skończę aktualizować moją pętlę nad danymi: czy mogę ręcznie uruchomić reindex, aby rozwiązać ten problem dla konkretnych identyfikatorów produktów?
snh_nl
Dziwne. przy użyciu metody 2. Otrzymuję filtr o nieznanym błędzie według kolumny `` Złapany wyjątek: SQLSTATE [42S22]: Nie znaleziono kolumny: 1054 Nieznana kolumna 'katalog_produktu_wartość.wartość_id' na 'liście pól', zapytanie brzmiało: WYBIERZ catalog_product_entity. value_idZ catalog_product_entityGDZIE (identyfikator_obiektu = 4 ORAZ identyfikator_atrybutu = '68 'ORAZ identyfikator_użytkownika = '29') `` nie spodziewałem się tego. Działa na 1.9.3.2
snh_nl
1
Zaoszczędził mi godziny pracy.
dipole_moment
3

Aktualizacja

Szukam najszybszej i niezawodnej metody masowej aktualizacji atrybutów

„Masowa aktualizacja atrybutów” dla atrybutów lub produktów?

Pomyśl, że aktualizacja wielu atrybutów jest już odpowiedzią, ale w przypadku produktów może to być przydatne ...

Jeśli chcesz zaktualizować produkty z kolekcji, nie powinieneś tego robić ...

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

Spowoduje to wysłanie zdarzeń, odbudowanie cenników i indeksów. Dzięki temu żadne zdarzenia (i niektóre inne rzeczy) nie są pomijane i są znacznie szybsze.

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

Aby uniknąć aktualizacji pricerule, możesz dodać ...

$product->setIsMassupdate(true);

Aby wyłączyć / włączyć reindeks w locie, spójrz na to ... 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();
    }
}

A także opróżnianie pamięci podręcznej przed aktualizacją masową (produktu) może zwiększyć wydajność ...

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

Niektóre liczby z debugowania tutaj: https://github.com/Flagbit/Magento-ChangeAttributeSet/issues/16


Mage::getSingleton('catalog/product_action')->updateAttributes(...) wydaje się nie być najszybszą metodą ... przynajmniej nie z włączoną konfiguracją listy odtwarzania i włączonymi płaskimi stołami ...

  • saveAttribute()

    $product = Mage::getModel('catalog/product')->load($productId);
    $resource = $product->getResource();
    $product->setData($attributeCode, $attributeValue);
    $resource->saveAttribute($product, $attributeCode);
    • Razem Czas ścienny (mikrosekund): 437,787 mikrosekund
    • Razem Procesor (mikrosekundy): 423,600 mikrosekund
    • Razem MemUse (bajty): 4 433 848 bajtów
    • Razem PeakMemUse (bytes): 4,395,128 bajtów
    • Liczba wywołań funkcji: 25 711
  • updateAttributes()

    Mage::getSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array($attributeCode => $attributeValue),
        $storeId
    );
    • Razem Czas ścienny (mikrosekund): 36676,950 mikrosekund
    • Razem Procesor (mikrosekundy): 3 122 064 mikrosekund
    • Razem MemUse (bytes): 8,174,792 bajtów
    • Razem PeakMemUse (bytes): 8 199,192 bajtów
    • Liczba wywołań funkcji: 150,132
  • updateAttributes() (singleton zasobów)

    Mage::getResourceSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array( $attributeCode => $attributeValue),
        $storeId
    );
    • Razem Czas ścienny (mikrosekund): 94155 mikrosekund
    • Razem Procesor (mikrosekundy): 48 568 mikrosekund
    • Razem MemUse (bytes): 1426304 bajty
    • Razem PeakMemUse (bytes): 1.370,456 bajtów
    • Liczba wywołań funkcji: 2221
sv3n
źródło
możesz przejrzeć moją odpowiedź, aby zrozumieć, dlaczego funkcja ta zajmuje różne czasy ...
Fra
W przypadku danych rozwijanych updateAttributes() (resource singleton)bierze rzeczywistą wartość administratora? lub id elementu rozwijanego? (jakoś zawsze nie otrzymujemy żadnej wartości / pustej wartości przy użyciu tej metody, tzn. nic nie zostało zaznaczone
snh_nl
@ snh_nl musisz użyć identyfikatora - przecinek oddzielony atrybutami wielokrotnego wyboru.
sv3n