Skip to content

Commit

Permalink
Optimize child count updater
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverSkroblin committed Apr 27, 2020
1 parent 4e65200 commit 8289d01
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
Expand Up @@ -3,7 +3,6 @@
namespace Shopware\Core\Content\Product\DataAbstractionLayer;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\DeadlockException;
use Shopware\Core\Content\Product\Aggregate\ProductKeywordDictionary\ProductKeywordDictionaryDefinition;
use Shopware\Core\Content\Product\Aggregate\ProductSearchKeyword\ProductSearchKeywordDefinition;
use Shopware\Core\Content\Product\ProductEntity;
Expand Down Expand Up @@ -151,7 +150,7 @@ private function insertKeywords(array $keywords): void
// try batch insert
try {
$queue->execute();
} catch (DeadlockException $e) {
} catch (\Exception $e) {
// catch deadlock exception and retry with single insert
$query = new RetryableQuery(
$this->connection->prepare('
Expand All @@ -176,7 +175,7 @@ private function insertDictionary(array $dictionary): void
// try batch insert
try {
$queue->execute();
} catch (DeadlockException $e) {
} catch (\Exception $e) {
// catch deadlock exception and retry with single insert
$query = new RetryableQuery(
$this->connection->prepare('INSERT IGNORE INTO `product_keyword_dictionary` (`id`, `language_id`, `keyword`) VALUES (:id, :language_id, :keyword)')
Expand Down
18 changes: 0 additions & 18 deletions src/Core/Framework/DataAbstractionLayer/Dbal/EntityReader.php
Expand Up @@ -1022,24 +1022,6 @@ private function fetchAssociations(
}
}

// $associations = $fields->filter(static function (Field $field) {
// return $field instanceof OneToOneAssociationField || $field instanceof ManyToOneAssociationField;
// });
//
// foreach ($associations as $association) {
// $this->loadToOne($association, $context, $collection, $criteria);
// }
//
// $associations = $fields->filterInstance(OneToManyAssociationField::class);
// foreach ($associations as $association) {
// $this->loadOneToMany($criteria, $definition, $association, $context, $collection);
// }
//
// $associations = $fields->filterInstance(ManyToManyAssociationField::class);
// foreach ($associations as $association) {
// $this->loadManyToMany($criteria, $association, $context, $collection);
// }

foreach ($collection as $struct) {
$struct->removeExtension(self::INTERNAL_MAPPING_STORAGE);
}
Expand Down
Expand Up @@ -3,11 +3,13 @@
namespace Shopware\Core\Framework\DataAbstractionLayer\Indexing;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\DeadlockException;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
use Shopware\Core\Framework\DataAbstractionLayer\DefinitionInstanceRegistry;
use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\FetchModeHelper;
use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\Uuid\Uuid;

class ChildCountUpdater
Expand All @@ -32,11 +34,58 @@ public function update(string $entity, array $parentIds, Context $context): void
{
$definition = $this->registry->getByEntityName($entity);

$entityName = $definition->getEntityName();
if (empty($parentIds)) {
return;
}

try {
// try update all ids with a single sql statement, this works only if no other process writes this table
$this->trySingleUpdate($definition, $parentIds, $context);
} catch (DeadlockException $e) {
// deadlock will appear when another process tries to write the same records
$this->doMultiUpdate($definition, $parentIds, $context);
}
}

private function trySingleUpdate(EntityDefinition $definition, array $parentIds, Context $context): void
{
$entity = $definition->getEntityName();
$versionAware = $definition->isVersionAware();

$sql = sprintf(
'UPDATE #entity# as parent
LEFT JOIN
(
SELECT parent_id, count(id) total
FROM #entity#
%s
GROUP BY parent_id
) child ON parent.id = child.parent_id
SET parent.child_count = IFNULL(child.total, 0)
WHERE parent.id IN (:ids)
%s',
$versionAware ? 'WHERE version_id = :version' : '',
$versionAware ? 'AND parent.version_id = :version' : ''
);

$sql = str_replace(
['#entity#'],
[EntityDefinitionQueryHelper::escape($entity)],
$sql
);

$params = ['ids' => Uuid::fromHexToBytesList($parentIds)];
if ($versionAware) {
$params['version'] = Uuid::fromHexToBytes($context->getVersionId());
}

$this->connection->executeUpdate($sql, $params, ['ids' => Connection::PARAM_STR_ARRAY]);
}

private function doMultiUpdate(EntityDefinition $definition, array $parentIds, Context $context): void
{
$entityName = $definition->getEntityName();

$query = $this->connection->createQueryBuilder();
$query->select([
'LOWER(HEX(parent_id)) as id',
Expand Down

0 comments on commit 8289d01

Please sign in to comment.