Skip to content

Commit b7fee19

Browse files
committed
ACP2E-2033: [Performance issue] Price indexer works slow
- added indexer hint
1 parent 2abc466 commit b7fee19

File tree

1 file changed

+76
-51
lines changed
  • app/code/Magento/Bundle/Model/ResourceModel/Indexer

1 file changed

+76
-51
lines changed

app/code/Magento/Bundle/Model/ResourceModel/Indexer/Price.php

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
namespace Magento\Bundle\Model\ResourceModel\Indexer;
77

88
use Magento\Catalog\Api\Data\ProductInterface;
9-
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\BasePriceModifier;
10-
use Magento\Framework\DB\Select;
11-
use Magento\Framework\Indexer\DimensionalIndexerInterface;
12-
use Magento\Framework\EntityManager\MetadataPool;
139
use Magento\Catalog\Model\Indexer\Product\Price\TableMaintainer;
14-
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructureFactory;
10+
use Magento\Catalog\Model\Product\Attribute\Source\Status;
11+
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\BasePriceModifier;
1512
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructure;
13+
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructureFactory;
1614
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Query\JoinAttributeProcessor;
15+
use Magento\CatalogInventory\Model\Stock;
1716
use Magento\Customer\Model\Indexer\CustomerGroupDimensionProvider;
17+
use Magento\Framework\DB\Select;
18+
use Magento\Framework\EntityManager\MetadataPool;
19+
use Magento\Framework\Indexer\DimensionalIndexerInterface;
1820
use Magento\Store\Model\Indexer\WebsiteDimensionProvider;
19-
use Magento\Catalog\Model\Product\Attribute\Source\Status;
20-
use Magento\CatalogInventory\Model\Stock;
2121

2222
/**
2323
* Bundle products Price indexer resource model
@@ -671,53 +671,78 @@ private function calculateFixedBundleSelectionPrice()
671671
* @return void
672672
* @throws \Exception
673673
*/
674-
private function calculateDynamicBundleSelectionPrice($dimensions)
674+
private function calculateDynamicBundleSelectionPrice(array $dimensions): void
675675
{
676676
$connection = $this->getConnection();
677-
678-
$price = 'idx.min_price * bs.selection_qty';
679-
$specialExpr = $connection->getCheckSql(
680-
'i.special_price > 0 AND i.special_price < 100',
681-
'ROUND(' . $price . ' * (i.special_price / 100), 4)',
682-
$price
683-
);
684-
$tierExpr = $connection->getCheckSql(
685-
'i.tier_percent IS NOT NULL',
686-
'ROUND((1 - i.tier_percent / 100) * ' . $price . ', 4)',
687-
'NULL'
688-
);
689-
$priceExpr = $connection->getLeastSql(
690-
[
691-
$specialExpr,
692-
$connection->getIfNullSql($tierExpr, $price),
693-
]
694-
);
695-
696-
$select = $this->getBaseBundleSelectionPriceSelect();
697-
$select->join(
698-
['idx' => $this->getMainTable($dimensions)],
699-
'bs.product_id = idx.entity_id AND i.customer_group_id = idx.customer_group_id' .
700-
' AND i.website_id = idx.website_id',
701-
[]
702-
)->where(
703-
'i.price_type=?',
704-
\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC
705-
)->columns(
706-
[
707-
'group_type' => $connection->getCheckSql("bo.type = 'select' OR bo.type = 'radio'", '0', '1'),
708-
'is_required' => 'bo.required',
709-
'price' => $priceExpr,
710-
'tier_price' => $tierExpr,
711-
]
712-
);
713-
$select->join(
714-
['si' => $this->getTable('cataloginventory_stock_status')],
715-
'si.product_id = bs.product_id',
716-
[]
677+
$insertColumns = [
678+
'entity_id',
679+
'customer_group_id',
680+
'website_id',
681+
'option_id',
682+
'selection_id',
683+
'group_type',
684+
'is_required',
685+
'price',
686+
'tier_price'
687+
];
688+
$insertColumns = array_map(function ($item) use ($connection) {
689+
return $connection->quoteIdentifier($item);
690+
}, $insertColumns);
691+
$updateValues = [];
692+
foreach ($insertColumns as $column) {
693+
$updateValues[] = sprintf("%s = VALUES(%s)", $column, $column);
694+
}
695+
$selectColumns = [
696+
'`i`.`entity_id`',
697+
'`i`.`customer_group_id`',
698+
'`i`.`website_id`',
699+
'`bo`.`option_id`',
700+
'`bs`.`selection_id`',
701+
"IF(bo.type = 'select' OR bo.type = 'radio', 0, 1) AS `group_type`",
702+
"`bo`.`required` AS `is_required`",
703+
'LEAST(IF(i.special_price > 0 AND i.special_price < 100,
704+
ROUND(idx.min_price * bs.selection_qty * (i.special_price / 100), 4), idx.min_price * bs.selection_qty),
705+
IFNULL((IF(i.tier_percent IS NOT NULL,
706+
ROUND((1 - i.tier_percent / 100) * idx.min_price * bs.selection_qty, 4), NULL)),
707+
idx.min_price * bs.selection_qty)) AS `price`',
708+
'IF(i.tier_percent IS NOT NULL, ROUND((1 - i.tier_percent / 100) * idx.min_price * bs.selection_qty, 4),
709+
NULL) AS `tier_price`'
710+
];
711+
$selectFrom = [
712+
'`' . $this->getBundlePriceTable() . '` AS `i`',
713+
'INNER JOIN `' . $this->getTable('catalog_product_entity') .
714+
'` AS `parent_product` ON parent_product.entity_id = i.entity_id AND
715+
(parent_product.created_in <= 1 AND parent_product.updated_in > 1)',
716+
'INNER JOIN `' . $this->getTable('catalog_product_bundle_option') . '` AS `bo`
717+
ON bo.parent_id = parent_product.row_id',
718+
'INNER JOIN `' . $this->getTable('catalog_product_bundle_selection') . '` AS `bs`
719+
ON bs.option_id = bo.option_id',
720+
'INNER JOIN `' . $this->getMainTable($dimensions) . '` AS `idx` USE INDEX (PRIMARY)
721+
ON bs.product_id = idx.entity_id AND i.customer_group_id = idx.customer_group_id AND
722+
i.website_id = idx.website_id',
723+
'INNER JOIN `' . $this->getTable('cataloginventory_stock_status') . '` AS `si`
724+
ON si.product_id = bs.product_id'
725+
];
726+
$selectWhere = [
727+
$connection->quoteInto('si.stock_status = ?', Stock::STOCK_IN_STOCK, \Zend_Db::INT_TYPE),
728+
$connection->quoteInto(
729+
'i.price_type = ?',
730+
\Magento\Bundle\Model\Product\Price::PRICE_TYPE_DYNAMIC,
731+
\Zend_Db::INT_TYPE
732+
)
733+
];
734+
$select = sprintf(
735+
"SELECT %s FROM %s WHERE %s",
736+
implode(",", $selectColumns),
737+
implode("\n", $selectFrom),
738+
implode(" AND ", $selectWhere)
717739
);
718-
$select->where('si.stock_status = ?', Stock::STOCK_IN_STOCK);
719-
720-
$this->tableMaintainer->insertFromSelect($select, $this->getBundleSelectionTable(), []);
740+
$connection->query(sprintf(
741+
"INSERT INTO `catalog_product_index_price_bundle_sel_temp` (%s) %s ON DUPLICATE KEY UPDATE %s",
742+
implode(",", $insertColumns),
743+
$select,
744+
implode(",", $updateValues)
745+
));
721746
}
722747

723748
/**

0 commit comments

Comments
 (0)