Skip to content

Commit

Permalink
TASK: Make restrictionrelation less dependent subquery
Browse files Browse the repository at this point in the history
Should improve query performance, especially in large datasets as
the subqueries depend on more constant values versus values from
the main query.
  • Loading branch information
kitsunet committed Dec 3, 2023
1 parent 50b6540 commit 953cc20
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public function findNodeAggregateById(
->select('n.*, h.name, h.contentstreamid, h.dimensionspacepoint AS covereddimensionspacepoint, r.dimensionspacepointhash AS disableddimensionspacepointhash')
->from($this->tableNamePrefix . '_hierarchyrelation', 'h')
->innerJoin('h', $this->tableNamePrefix . '_node', 'n', 'n.relationanchorpoint = h.childnodeanchor')
->leftJoin('h', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = n.nodeaggregateid AND r.contentstreamid = h.contentstreamid AND r.affectednodeaggregateid = n.nodeaggregateid AND r.dimensionspacepointhash = h.dimensionspacepointhash')
->leftJoin('h', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = n.nodeaggregateid AND r.contentstreamid = :contentStreamId AND r.affectednodeaggregateid = n.nodeaggregateid AND r.dimensionspacepointhash = h.dimensionspacepointhash')
->where('n.nodeaggregateid = :nodeAggregateId')
->andWhere('h.contentstreamid = :contentStreamId')
->setParameters([
Expand All @@ -207,7 +207,7 @@ public function findParentNodeAggregates(
->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ph', 'ph.childnodeanchor = pn.relationanchorpoint')
->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ch', 'ch.parentnodeanchor = pn.relationanchorpoint')
->innerJoin('ch', $this->tableNamePrefix . '_node', 'cn', 'cn.relationanchorpoint = ch.childnodeanchor')
->leftJoin('ph', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = pn.nodeaggregateid AND r.contentstreamid = ph.contentstreamid AND r.affectednodeaggregateid = pn.nodeaggregateid AND r.dimensionspacepointhash = ph.dimensionspacepointhash')
->leftJoin('ph', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = pn.nodeaggregateid AND r.contentstreamid = :contentStreamId AND r.affectednodeaggregateid = pn.nodeaggregateid AND r.dimensionspacepointhash = ph.dimensionspacepointhash')
->where('cn.nodeaggregateid = :nodeAggregateId')
->andWhere('ph.contentstreamid = :contentStreamId')
->andWhere('ch.contentstreamid = :contentStreamId')
Expand Down Expand Up @@ -238,7 +238,7 @@ public function findParentNodeAggregateByChildOriginDimensionSpacePoint(
->select('n.*, h.name, h.contentstreamid, h.dimensionspacepoint AS covereddimensionspacepoint, r.dimensionspacepointhash AS disableddimensionspacepointhash')
->from($this->tableNamePrefix . '_node', 'n')
->innerJoin('n', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = n.relationanchorpoint')
->leftJoin('h', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = n.nodeaggregateid AND r.contentstreamid = h.contentstreamid AND r.affectednodeaggregateid = n.nodeaggregateid AND r.dimensionspacepointhash = h.dimensionspacepointhash')
->leftJoin('h', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = n.nodeaggregateid AND r.contentstreamid = :contentStreamId AND r.affectednodeaggregateid = n.nodeaggregateid AND r.dimensionspacepointhash = h.dimensionspacepointhash')
->where('n.nodeaggregateid = (' . $subQueryBuilder->getSQL() . ')')
->andWhere('h.contentstreamid = :contentStreamId')
->setParameters([
Expand Down Expand Up @@ -374,7 +374,7 @@ private function buildChildNodeAggregateQuery(NodeAggregateId $parentNodeAggrega
->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ph', 'ph.childnodeanchor = pn.relationanchorpoint')
->innerJoin('pn', $this->tableNamePrefix . '_hierarchyrelation', 'ch', 'ch.parentnodeanchor = pn.relationanchorpoint')
->innerJoin('ch', $this->tableNamePrefix . '_node', 'cn', 'cn.relationanchorpoint = ch.childnodeanchor')
->leftJoin('pn', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = pn.nodeaggregateid AND r.contentstreamid = ph.contentstreamid AND r.affectednodeaggregateid = pn.nodeaggregateid AND r.dimensionspacepointhash = ph.dimensionspacepointhash')
->leftJoin('pn', $this->tableNamePrefix . '_restrictionrelation', 'r', 'r.originnodeaggregateid = pn.nodeaggregateid AND r.contentstreamid = :contentStreamId AND r.affectednodeaggregateid = pn.nodeaggregateid AND r.dimensionspacepointhash = ph.dimensionspacepointhash')
->where('pn.nodeaggregateid = :parentNodeAggregateId')
->andWhere('ph.contentstreamid = :contentStreamId')
->andWhere('ch.contentstreamid = :contentStreamId')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ public function findNodeById(NodeAggregateId $nodeAggregateId): ?Node
->where('n.nodeaggregateid = :nodeAggregateId')->setParameter('nodeAggregateId', $nodeAggregateId->value)
->andWhere('h.contentstreamid = :contentStreamId')->setParameter('contentStreamId', $this->contentStreamId->value)
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash')->setParameter('dimensionSpacePointHash', $this->dimensionSpacePoint->hash);
$this->addRestrictionRelationConstraints($queryBuilder);
$this->addRestrictionRelationConstraints($queryBuilder, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');
return $this->fetchNode($queryBuilder);
}

Expand All @@ -190,7 +190,7 @@ public function findRootNodeByType(NodeTypeName $nodeTypeName): ?Node
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash')->setParameter('dimensionSpacePointHash', $this->dimensionSpacePoint->hash)
->andWhere('n.classification = :nodeAggregateClassification')
->setParameter('nodeAggregateClassification', NodeAggregateClassification::CLASSIFICATION_ROOT->value);
$this->addRestrictionRelationConstraints($queryBuilder);
$this->addRestrictionRelationConstraints($queryBuilder, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');
return $this->fetchNode($queryBuilder);
}

Expand All @@ -207,7 +207,7 @@ public function findParentNode(NodeAggregateId $childNodeAggregateId): ?Node
->andWhere('ch.contentstreamid = :contentStreamId')
->andWhere('ph.dimensionspacepointhash = :dimensionSpacePointHash')->setParameter('dimensionSpacePointHash', $this->dimensionSpacePoint->hash)
->andWhere('ch.dimensionspacepointhash = :dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilder, 'cn', 'ch');
$this->addRestrictionRelationConstraints($queryBuilder, 'cn', 'ch', ':contentStreamId', ':dimensionSpacePointHash');
return $this->fetchNode($queryBuilder);
}

Expand Down Expand Up @@ -247,7 +247,7 @@ private function findChildNodeConnectedThroughEdgeName(NodeAggregateId $parentNo
->andWhere('h.contentstreamid = :contentStreamId')->setParameter('contentStreamId', $this->contentStreamId->value)
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash')->setParameter('dimensionSpacePointHash', $this->dimensionSpacePoint->hash)
->andWhere('h.name = :edgeName')->setParameter('edgeName', $nodeName->value);
$this->addRestrictionRelationConstraints($queryBuilder, 'cn');
$this->addRestrictionRelationConstraints($queryBuilder, 'cn', 'h', ':contentStreamId', ':dimensionSpacePointHash');
return $this->fetchNode($queryBuilder);
}

Expand Down Expand Up @@ -296,7 +296,7 @@ public function findSubtree(NodeAggregateId $entryNodeAggregateId, FindSubtreeFi
->where('h.contentstreamid = :contentStreamId')
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash')
->andWhere('n.nodeaggregateid = :entryNodeAggregateId');
$this->addRestrictionRelationConstraints($queryBuilderInitial);
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderRecursive = $this->createQueryBuilder()
->select('c.*, h.name, h.contentstreamid, p.nodeaggregateid AS parentNodeAggregateId, p.level + 1 AS level, h.position')
Expand All @@ -311,7 +311,7 @@ public function findSubtree(NodeAggregateId $entryNodeAggregateId, FindSubtreeFi
if ($filter->nodeTypes !== null) {
$this->addNodeTypeCriteria($queryBuilderRecursive, $filter->nodeTypes, 'c');
}
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'c');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'c', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderCte = $this->createQueryBuilder()
->select('*')
Expand Down Expand Up @@ -388,7 +388,7 @@ public function findClosestNode(NodeAggregateId $entryNodeAggregateId, FindClose
->andWhere('ph.contentstreamid = :contentStreamId')
->andWhere('ph.dimensionspacepointhash = :dimensionSpacePointHash')
->andWhere('n.nodeaggregateid = :entryNodeAggregateId');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'ph');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'ph', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderRecursive = $this->createQueryBuilder()
->select('p.*, h.name, h.contentstreamid, h.parentnodeanchor')
Expand All @@ -397,7 +397,7 @@ public function findClosestNode(NodeAggregateId $entryNodeAggregateId, FindClose
->innerJoin('p', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = p.relationanchorpoint')
->where('h.contentstreamid = :contentStreamId')
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'p');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'p', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderCte = $this->createQueryBuilder()
->select('*')
Expand Down Expand Up @@ -497,18 +497,32 @@ private function createUniqueParameterName(): string
return 'param_' . (++$this->dynamicParameterCount);
}

private function addRestrictionRelationConstraints(QueryBuilder $queryBuilder, string $nodeTableAlias = 'n', string $hierarchyRelationTableAlias = 'h'): void
/**
* @param QueryBuilder $queryBuilder
* @param string $nodeTableAlias
* @param string $hierarchyRelationTableAlias
* @param string|null $contentStreamIdParameter if not given, condition will be on the hierachy relation content stream id
* @param string|null $dimensionspacePointHashParameter if not given, condition will be on the hierachy relation dimension space point hash
* @return void
*/
private function addRestrictionRelationConstraints(QueryBuilder $queryBuilder, string $nodeTableAlias = 'n', string $hierarchyRelationTableAlias = 'h', ?string $contentStreamIdParameter = null, ?string $dimensionspacePointHashParameter = null): void
{
if ($this->visibilityConstraints->isDisabledContentShown()) {
return;
}

$nodeTablePrefix = $nodeTableAlias === '' ? '' : $nodeTableAlias . '.';
$hierarchyRelationTablePrefix = $hierarchyRelationTableAlias === '' ? '' : $hierarchyRelationTableAlias . '.';

$contentStreamIdCondition = 'r.contentstreamid = ' . ($contentStreamIdParameter ?? ($hierarchyRelationTablePrefix . 'contentstreamid'));

$dimensionspacePointHashCondition = 'r.dimensionspacepointhash = ' . ($dimensionspacePointHashParameter ?? ($hierarchyRelationTablePrefix . 'dimensionspacepointhash'));

$subQueryBuilder = $this->createQueryBuilder()
->select('1')
->from($this->tableNamePrefix . '_restrictionrelation', 'r')
->where('r.contentstreamid = ' . $hierarchyRelationTablePrefix . 'contentstreamid')
->andWhere('r.dimensionspacepointhash = ' . $hierarchyRelationTablePrefix . 'dimensionspacepointhash')
->where($contentStreamIdCondition)
->andWhere($dimensionspacePointHashCondition)
->andWhere('r.affectednodeaggregateid = ' . $nodeTablePrefix . 'nodeaggregateid');
$queryBuilder->andWhere(
'NOT EXISTS (' . $subQueryBuilder->getSQL() . ')'
Expand Down Expand Up @@ -626,7 +640,7 @@ private function buildChildNodesQuery(NodeAggregateId $parentNodeAggregateId, Fi
if ($filter->propertyValue !== null) {
$this->addPropertyValueConstraints($queryBuilder, $filter->propertyValue);
}
$this->addRestrictionRelationConstraints($queryBuilder);
$this->addRestrictionRelationConstraints($queryBuilder, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');
return $queryBuilder;
}

Expand All @@ -646,8 +660,8 @@ private function buildReferencesQuery(bool $backReferences, NodeAggregateId $nod
->andWhere('sh.dimensionspacepointhash = :dimensionSpacePointHash')
->andWhere('dh.contentstreamid = :contentStreamId')->setParameter('contentStreamId', $this->contentStreamId->value)
->andWhere('sh.contentstreamid = :contentStreamId');
$this->addRestrictionRelationConstraints($queryBuilder, 'dn', 'dh');
$this->addRestrictionRelationConstraints($queryBuilder, 'sn', 'sh');
$this->addRestrictionRelationConstraints($queryBuilder, 'dn', 'dh', ':contentStreamId', ':dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilder, 'sn', 'sh', ':contentStreamId', ':dimensionSpacePointHash');
if ($filter->nodeTypes !== null) {
$this->addNodeTypeCriteria($queryBuilder, $filter->nodeTypes, "{$destinationTablePrefix}n");
}
Expand Down Expand Up @@ -713,7 +727,7 @@ private function buildSiblingsQuery(bool $preceding, NodeAggregateId $siblingNod
->andWhere('h.position ' . ($preceding ? '<' : '>') . ' (' . $siblingPositionSubQuery->getSQL() . ')')
->orderBy('h.position', $preceding ? 'DESC' : 'ASC');

$this->addRestrictionRelationConstraints($queryBuilder);
$this->addRestrictionRelationConstraints($queryBuilder, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');
if ($filter->nodeTypes !== null) {
$this->addNodeTypeCriteria($queryBuilder, $filter->nodeTypes);
}
Expand Down Expand Up @@ -746,8 +760,8 @@ private function buildAncestorNodesQueries(NodeAggregateId $entryNodeAggregateId
->andWhere('ph.contentstreamid = :contentStreamId')
->andWhere('ph.dimensionspacepointhash = :dimensionSpacePointHash')
->andWhere('c.nodeaggregateid = :entryNodeAggregateId');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'ph');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'c', 'ch');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'ph', ':contentStreamId', ':dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'c', 'ch', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderRecursive = $this->createQueryBuilder()
->select('p.*, h.name, h.contentstreamid, h.parentnodeanchor')
Expand All @@ -756,7 +770,7 @@ private function buildAncestorNodesQueries(NodeAggregateId $entryNodeAggregateId
->innerJoin('p', $this->tableNamePrefix . '_hierarchyrelation', 'h', 'h.childnodeanchor = p.relationanchorpoint')
->where('h.contentstreamid = :contentStreamId')
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'p');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'p', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderCte = $this->createQueryBuilder()
->select('*')
Expand Down Expand Up @@ -788,7 +802,7 @@ private function buildDescendantNodesQueries(NodeAggregateId $entryNodeAggregate
->andWhere('ph.contentstreamid = :contentStreamId')
->andWhere('ph.dimensionspacepointhash = :dimensionSpacePointHash')
->andWhere('p.nodeaggregateid = :entryNodeAggregateId');
$this->addRestrictionRelationConstraints($queryBuilderInitial);
$this->addRestrictionRelationConstraints($queryBuilderInitial, 'n', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderRecursive = $this->createQueryBuilder()
->select('c.*, h.name, h.contentstreamid, p.nodeaggregateid AS parentNodeAggregateId, p.level + 1 AS level, h.position')
Expand All @@ -797,7 +811,7 @@ private function buildDescendantNodesQueries(NodeAggregateId $entryNodeAggregate
->innerJoin('p', $this->tableNamePrefix . '_node', 'c', 'c.relationanchorpoint = h.childnodeanchor')
->where('h.contentstreamid = :contentStreamId')
->andWhere('h.dimensionspacepointhash = :dimensionSpacePointHash');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'c');
$this->addRestrictionRelationConstraints($queryBuilderRecursive, 'c', 'h', ':contentStreamId', ':dimensionSpacePointHash');

$queryBuilderCte = $this->createQueryBuilder()
->select('*')
Expand Down

0 comments on commit 953cc20

Please sign in to comment.