Skip to content

Commit

Permalink
Add indexes to improve performance of some queries (#226)
Browse files Browse the repository at this point in the history
* Add indexes to improve performance of some queries

* Remove unnecessary distinct

* Add indexes to locale and stage dimension content fields

* Remove unnecessary select

* Remove not required join

* Use distinct only when filter by specific join

* Add some comment

* Add comment to remove joins with a subselect filter

* Update upgrade

* Add php doc
  • Loading branch information
alexander-schranz committed Oct 4, 2022
1 parent 16de307 commit 9e81f56
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
21 changes: 21 additions & 0 deletions Content/Infrastructure/Doctrine/MetadataLoader.php
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
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

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()
->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
@@ -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

0 comments on commit 9e81f56

Please sign in to comment.