Проблема переіндексації великого каталогу в Magento 2
Вихідні данні: Magento 2.3.1, каталог - 300K Проблема: переіндексація каталогу може відбуватись більше 24 годин (може й більше, ніхто не перевіряв)
Пошуки рішення привели до такого твіту:
а також до такого issue https://github.com/magento/magento2/issues/10531 .
Хоча обговоренню більше 2 років, здається воно актуальне і для 2.3.1.
Мені допомогли ці дві штуки:
-
задати великий batchRowsCount в di.xml
<type name="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\BatchSizeCalculator"> <arguments> <argument name="batchRowsCount" xsi:type="array"> <item name="default" xsi:type="number">500000</item> </argument> </arguments> </type>
-
збільшити $batchSize в /vendor/magento/module-catalog-inventory/Model/Indexer/ProductPriceIndexFilter.php (67)
public function __construct( StockConfigurationInterface $stockConfiguration, Item $stockItem, ResourceConnection $resourceConnection = null, $connectionName = 'indexer', Generator $batchQueryGenerator = null, $batchSize = 20000 ) { $this->stockConfiguration = $stockConfiguration; $this->stockItem = $stockItem; $this->resourceConnection = $resourceConnection ?: ObjectManager::getInstance()->get(ResourceConnection::class); $this->connectionName = $connectionName; $this->batchQueryGenerator = $batchQueryGenerator ?: ObjectManager::getInstance()->get(Generator::class); $this->batchSize = $batchSize; }
P.S. Ейфорія тривала не довго, аж до наступної переіндексації. Розслідування продовжилось і виплив ось такий issue - https://github.com/magento/magento2/issues/23077, який пов’язаний з неправильною роботою тригерів і створенням дублів товарів для індексації. Ну і власне виправлення - https://github.com/sebastien-kathmandu/magento2/pull/1/commits/444bc8d2805ab0c57a66e656332394f0123c63df.
Раніше у vendor/magento/framework/Mview/View/Subscription.php (принаймі у версії 2.2.5) було так:
foreach ($columnNames as $columnName) {
$columns[] = sprintf(
'NEW.%1$s != OLD.%1$s',
$this->connection->quoteIdentifier($columnName)
);
}
потім стало так:
foreach ($columnNames as $columnName) {
$columns[] = sprintf(
'NEW.%1$s <=> OLD.%1$s',
$this->connection->quoteIdentifier($columnName)
);
}
Фактично, від перевірки на нерівність двох змінних, перейшли до перевірки на рівність, що очевидно є помилкою, бо спричиняє лавиноподібне заповнення таблиць з префіксом cl. В якості виправлення запропоновано такий варіант:
foreach ($columnNames as $columnName) {
$columns[] = sprintf(
'NOT NEW.%1$s <=> OLD.%1$s',
$this->connection->quoteIdentifier($columnName)
);
}
Посилання
- Про те, як влаштована індексація в Magento 2 можна почитати тут - https://belvg.com/blog/how-it-works-magento-2-partial-index.html.