Skip to content

Commit ca9cef2

Browse files
committed
ACP2E-3891: Categories in admin are loading very slow
1 parent 5a1fa62 commit ca9cef2

File tree

2 files changed

+54
-28
lines changed

2 files changed

+54
-28
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use Magento\Framework\App\Config\ScopeConfigInterface;
1212
use Magento\Framework\DB\Select;
1313
use Magento\Store\Model\ScopeInterface;
14+
use Magento\Framework\DB\Adapter\AdapterInterface;
15+
use Magento\Framework\DB\Ddl\Table;
1416

1517
/**
1618
* Category resource collection
@@ -370,41 +372,59 @@ public function loadProductCount($items, $countRegular = true, $countAnchor = tr
370372
* @param array $categoryIds
371373
* @param int $websiteId
372374
* @return array
375+
* @throws \Zend_Db_Exception
373376
*/
374377
private function getCountFromCategoryTableBulk(
375378
array $categoryIds,
376379
int $websiteId
377380
) : array {
378381
$connection = $this->_conn;
379-
$tempTableName = $connection->getTableName('temp_category_descendants_' . uniqid());
380-
$connection->query("CREATE TEMPORARY TABLE {$tempTableName} (
381-
category_id INT UNSIGNED NOT NULL,
382-
descendant_id INT UNSIGNED NOT NULL,
383-
PRIMARY KEY (category_id, descendant_id)
384-
)");
385-
$selectDescendants = clone $connection->select();
386-
$selectDescendants->from(
387-
['ce' => $this->getTable('catalog_category_entity')],
388-
['category_id' => 'ce.entity_id', 'descendant_id' => 'ce2.entity_id']
389-
)
382+
$tempTableName = 'temp_category_descendants_' . uniqid();
383+
$tempTable = $connection->newTable($tempTableName)
384+
->addColumn(
385+
'category_id',
386+
Table::TYPE_INTEGER,
387+
null,
388+
['unsigned' => true, 'nullable' => false],
389+
'Category ID'
390+
)
391+
->addColumn(
392+
'descendant_id',
393+
Table::TYPE_INTEGER,
394+
null,
395+
['unsigned' => true, 'nullable' => false],
396+
'Descendant ID'
397+
)
398+
->addIndex(
399+
$connection->getIndexName($tempTableName, ['category_id', 'descendant_id']),
400+
['category_id', 'descendant_id'],
401+
['type' => AdapterInterface::INDEX_TYPE_PRIMARY]
402+
);
403+
$connection->createTemporaryTable($tempTable);
404+
$selectDescendants = $connection->select()
405+
->from(
406+
['ce' => $this->getTable('catalog_category_entity')],
407+
['category_id' => 'ce.entity_id', 'descendant_id' => 'ce2.entity_id']
408+
)
390409
->joinInner(
391410
['ce2' => $this->getTable('catalog_category_entity')],
392411
'ce2.path LIKE CONCAT(ce.path, \'/%\') OR ce2.entity_id = ce.entity_id',
393412
[]
394413
)
395414
->where('ce.entity_id IN (?)', $categoryIds);
415+
396416
$connection->query(
397417
$connection->insertFromSelect(
398418
$selectDescendants,
399419
$tempTableName,
400420
['category_id', 'descendant_id']
401421
)
402422
);
403-
$select = clone $connection->select();
404-
$select->from(
405-
['t' => $tempTableName],
406-
['category_id' => 't.category_id']
407-
)
423+
$select = $connection->select()
424+
->from(
425+
['t' => $tempTableName],
426+
['category_id' => 't.category_id']
427+
)
408428
->joinLeft(
409429
['cp' => $this->getTable('catalog_category_product')],
410430
'cp.category_id = t.descendant_id',
@@ -419,7 +439,7 @@ private function getCountFromCategoryTableBulk(
419439
}
420440
$select->group('t.category_id');
421441
$result = $connection->fetchPairs($select);
422-
$connection->query("DROP TEMPORARY TABLE {$tempTableName}");
442+
$connection->dropTemporaryTable($tempTableName);
423443
$counts = array_fill_keys($categoryIds, 0);
424444
foreach ($result as $categoryId => $count) {
425445
$counts[$categoryId] = (int)$count;

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Category/CollectionTest.php

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -245,23 +245,29 @@ public function testLoadProductCountCallsBulkMethodForLargeCategoryCount()
245245
$this->storeManager->method('getStore')->with($storeId)->willReturn($storeMock);
246246
$this->connection->method('select')->willReturn($this->select);
247247
$counts = array_fill_keys($categoryIds, 5);
248+
$tableMock = $this->createMock(\Magento\Framework\DB\Ddl\Table::class);
249+
$tableMock->method('addColumn')->willReturnSelf();
250+
$tableMock->method('addIndex')->willReturnSelf();
251+
$this->connection->method('newTable')
252+
->with($this->stringContains('temp_category_descendants_'))
253+
->willReturn($tableMock);
254+
$this->connection->expects($this->once())->method('createTemporaryTable')->with($tableMock);
255+
$this->connection->expects($this->once())->method('dropTemporaryTable')
256+
->with($this->stringContains('temp_category_descendants_'));
248257
$this->select->method('from')->willReturnSelf();
258+
$this->select->method('joinInner')->willReturnSelf();
259+
$this->select->method('where')->willReturnSelf();
260+
$this->connection->method('select')->willReturn($this->select);
261+
$this->connection->method('insertFromSelect')->willReturn('INSERT QUERY');
262+
$this->connection->method('query')->with('INSERT QUERY')->willReturnSelf();
263+
$this->select->method('from')->willReturnSelf();
264+
$this->select->method('joinLeft')->willReturnSelf();
265+
$this->select->method('join')->willReturnSelf();
249266
$this->select->method('where')->willReturnSelf();
250267
$this->select->method('group')->willReturnSelf();
251268
$this->connection->method('fetchPairs')
252269
->with($this->isInstanceOf(Select::class))
253270
->willReturn($counts);
254-
$tempTableName = 'temp_category_descendants_';
255-
$this->connection->method('query')->willReturn($tempTableName);
256-
$this->select->method('joinInner')->willReturnSelf();
257-
$this->connection->method('insertFromSelect')->willReturn('INSERT QUERY');
258-
$bulkSelectMock = $this->createMock(Select::class);
259-
$bulkSelectMock->method('from')->willReturnSelf();
260-
$bulkSelectMock->method('joinLeft')->willReturnSelf();
261-
$bulkSelectMock->method('join')->willReturnSelf();
262-
$bulkSelectMock->method('where')->willReturnSelf();
263-
$bulkSelectMock->method('group')->willReturnSelf();
264-
$this->connection->method('fetchPairs')->willReturn($counts);
265271
$this->collection->setProductStoreId($storeId);
266272
$this->collection->loadProductCount($items, false, true);
267273
}

0 commit comments

Comments
 (0)