Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add indexes to improve performance of some queries #226

Merged
merged 10 commits into from
Oct 4, 2022
21 changes: 21 additions & 0 deletions Content/Infrastructure/Doctrine/MetadataLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Doctrine\Inflector\InflectorFactory;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Sulu\Bundle\CategoryBundle\Entity\CategoryInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
Expand Down Expand Up @@ -45,6 +46,10 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
if ($reflection->implementsInterface(DimensionContentInterface::class)) {
$this->addField($metadata, 'stage', 'string', ['length' => 16, 'nullable' => false]);
$this->addField($metadata, 'locale', 'string', ['length' => 7, 'nullable' => true]);

$this->addIndex($metadata, 'idx_dimension', ['stage', 'locale']);
$this->addIndex($metadata, 'idx_locale', ['locale']);
$this->addIndex($metadata, 'idx_stage', ['stage']);
}

if ($reflection->implementsInterface(SeoInterface::class)) {
Expand All @@ -60,6 +65,8 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
if ($reflection->implementsInterface(TemplateInterface::class)) {
$this->addField($metadata, 'templateKey', 'string', ['length' => 32]);
$this->addField($metadata, 'templateData', 'json', ['nullable' => false]);

$this->addIndex($metadata, 'idx_template_key', ['templateKey']);
}

if ($reflection->implementsInterface(ExcerptInterface::class)) {
Expand Down Expand Up @@ -95,6 +102,9 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
if ($reflection->implementsInterface(WorkflowInterface::class)) {
$this->addField($metadata, 'workflowPlace', 'string', ['length' => 32, 'nullable' => true]);
$this->addField($metadata, 'workflowPublished', 'datetime_immutable', ['nullable' => true]);

$this->addIndex($metadata, 'idx_workflow_place', ['workflowPlace']);
$this->addIndex($metadata, 'idx_workflow_published', ['workflowPublished']);
}
}

Expand Down Expand Up @@ -198,6 +208,17 @@ private function addField(ClassMetadataInfo $metadata, string $name, string $typ
], $mapping));
}

/**
* @param ClassMetadataInfo<object> $metadata
* @param string[] $fields
*/
private function addIndex(ClassMetadataInfo $metadata, string $name, array $fields): void
{
$builder = new ClassMetadataBuilder($metadata);

$builder->addIndex($fields, $name);
}

/**
* @param ClassMetadataInfo<object> $metadata
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class ContentDataProviderRepository implements DataProviderRepositoryInterface
{
public const CONTENT_RICH_ENTITY_ALIAS = 'entity';
public const LOCALIZED_DIMENSION_CONTENT_ALIAS = 'localizedContent';
public const UNLOCALIZED_DIMENSION_CONTENT_ALIAS = 'unlocalizedContent';

/**
* @var ContentManagerInterface
Expand Down Expand Up @@ -404,6 +403,8 @@ protected function setSortByJoins(QueryBuilder $queryBuilder): array
*/
protected function appendRelation(QueryBuilder $queryBuilder, string $relation, array $values, string $operator, string $alias): array
{
$queryBuilder->distinct(); // TODO remove distinct and replace joins with subselect filter see: https://github.com/sulu/SuluContentBundle/pull/226
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created an issue for this. here some improvements could be made: #227


switch ($operator) {
case 'or':
return $this->appendRelationOr($queryBuilder, $relation, $values, $alias);
Expand Down Expand Up @@ -461,15 +462,13 @@ protected function createEntityIdsQueryBuilder(string $locale): QueryBuilder
: DimensionContentInterface::STAGE_LIVE;

return $this->entityManager->createQueryBuilder()
// no distinct used here else it would hurt performance of the query: https://github.com/sulu/SuluContentBundle/pull/226
// distinct only added in `appendRelation` methods where it is required
->select(self::CONTENT_RICH_ENTITY_ALIAS . '.' . $this->getEntityIdentifierFieldName() . ' as id')
->distinct()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hurts the performance a lot but is not necessary. All joins of filters should be created the way that no distinct is required here else we will run into a lot of performance issues.

Copy link
Member Author

@alexander-schranz alexander-schranz Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should in future have a look at the queries that we not longer have todo distinct as it seems have bad effects on this kind of queries. See #227

->from($this->contentRichEntityClass, self::CONTENT_RICH_ENTITY_ALIAS)
->innerJoin(self::CONTENT_RICH_ENTITY_ALIAS . '.dimensionContents', self::LOCALIZED_DIMENSION_CONTENT_ALIAS)
->andWhere(self::LOCALIZED_DIMENSION_CONTENT_ALIAS . '.stage = (:stage)')
->andWhere(self::LOCALIZED_DIMENSION_CONTENT_ALIAS . '.locale = (:locale)')
->innerJoin(self::CONTENT_RICH_ENTITY_ALIAS . '.dimensionContents', self::UNLOCALIZED_DIMENSION_CONTENT_ALIAS)
->andWhere(self::UNLOCALIZED_DIMENSION_CONTENT_ALIAS . '.stage = (:stage)')
->andWhere(self::UNLOCALIZED_DIMENSION_CONTENT_ALIAS . '.locale IS NULL')
->setParameter('stage', $stage)
->setParameter('locale', $locale);
}
Expand Down
15 changes: 15 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Upgrade

## 0.6.3

### Add dimension, templateKey, workflowPublished and workflowPlace indexes

Improve performance of the `*ContentDimension` tables with additional indexes for the database:

```sql
CREATE INDEX idx_dimension ON <your_entity>_content (stage, locale);
CREATE INDEX idx_locale ON <your_entity>_content (locale);
CREATE INDEX idx_stage ON <your_entity>_content (stage);
CREATE INDEX idx_template_key ON <your_entity>_content (templateKey);
CREATE INDEX idx_workflow_place ON <your_entity>_content (workflowPlace);
CREATE INDEX idx_workflow_published ON <your_entity>_content (workflowPublished);
```

## 0.6.0

### Adjusted ContentDataMapper to accept DimensionContentCollection instead of separate objects
Expand Down