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

!!! TASK: Split dimensionspacepoints into separate table to reduce data duplication #4790

Merged
merged 12 commits into from
Mar 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ private function transformDatasetToHierarchyRelationRecord(array $dataset): arra

return [
'contentstreamid' => $dataset['contentStreamId'],
'dimensionspacepoint' => $dimensionSpacePoint->toJson(),
'dimensionspacepointhash' => $dimensionSpacePoint->hash,
'parentnodeanchor' => $parentHierarchyRelation !== null ? $parentHierarchyRelation['childnodeanchor'] : 9999999,
'childnodeanchor' => $childHierarchyRelation !== null ? $childHierarchyRelation['childnodeanchor'] : 8888888,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRecord;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection\NodeRelationAnchorPoint;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ContentGraph;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
Expand Down Expand Up @@ -90,6 +91,7 @@ public function __construct(
private readonly NodeTypeManager $nodeTypeManager,
private readonly ProjectionContentGraph $projectionContentGraph,
private readonly string $tableNamePrefix,
private readonly DimensionSpacePointsRepository $dimensionSpacePointsRepository
) {
$this->checkpointStorage = new DbalCheckpointStorage(
$this->dbalClient->getConnection(),
Expand Down Expand Up @@ -174,6 +176,7 @@ private function truncateDatabaseTables(): void
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_node');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_hierarchyrelation');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_referencerelation');
$connection->executeQuery('TRUNCATE table ' . $this->tableNamePrefix . '_dimensionspacepoints');
}

public function canHandle(EventInterface $event): bool
Expand Down Expand Up @@ -599,7 +602,6 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void
childnodeanchor,
`name`,
position,
dimensionspacepoint,
dimensionspacepointhash,
subtreetags,
contentstreamid
Expand All @@ -609,7 +611,6 @@ private function whenContentStreamWasForked(ContentStreamWasForked $event): void
h.childnodeanchor,
h.name,
h.position,
h.dimensionspacepoint,
h.dimensionspacepointhash,
h.subtreetags,
"' . $event->newContentStreamId->value . '" AS contentstreamid
Expand Down Expand Up @@ -947,6 +948,8 @@ private function copyReferenceRelations(
private function whenDimensionSpacePointWasMoved(DimensionSpacePointWasMoved $event): void
{
$this->transactional(function () use ($event) {
$this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target);

// the ordering is important - we first update the OriginDimensionSpacePoints, as we need the
// hierarchy relations for this query. Then, we update the Hierarchy Relations.

Expand Down Expand Up @@ -985,7 +988,6 @@ function (NodeRecord $nodeRecord) use ($event) {
'
UPDATE ' . $this->tableNamePrefix . '_hierarchyrelation h
SET
h.dimensionspacepoint = :newDimensionSpacePoint,
h.dimensionspacepointhash = :newDimensionSpacePointHash
WHERE
h.dimensionspacepointhash = :originalDimensionSpacePointHash
Expand All @@ -994,7 +996,6 @@ function (NodeRecord $nodeRecord) use ($event) {
[
'originalDimensionSpacePointHash' => $event->source->hash,
'newDimensionSpacePointHash' => $event->target->hash,
'newDimensionSpacePoint' => $event->target->toJson(),
'contentStreamId' => $event->contentStreamId->value
]
);
Expand All @@ -1004,6 +1005,8 @@ function (NodeRecord $nodeRecord) use ($event) {
private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded $event): void
{
$this->transactional(function () use ($event) {
$this->dimensionSpacePointsRepository->insertDimensionSpacePoint($event->target);

// 1) hierarchy relations
$this->getDatabaseConnection()->executeStatement(
'
Expand All @@ -1013,7 +1016,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
`name`,
position,
subtreetags,
dimensionspacepoint,
dimensionspacepointhash,
contentstreamid
)
Expand All @@ -1023,7 +1025,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
h.name,
h.position,
h.subtreetags,
:newDimensionSpacePoint AS dimensionspacepoint,
:newDimensionSpacePointHash AS dimensionspacepointhash,
h.contentstreamid
FROM
Expand All @@ -1034,7 +1035,6 @@ private function whenDimensionShineThroughWasAdded(DimensionShineThroughWasAdded
'contentStreamId' => $event->contentStreamId->value,
'sourceDimensionSpacePointHash' => $event->source->hash,
'newDimensionSpacePointHash' => $event->target->hash,
'newDimensionSpacePoint' => $event->target->toJson(),
]
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Neos\ContentGraph\DoctrineDbalAdapter;

use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\NodeFactory;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\ProjectionContentGraph;
use Neos\ContentRepository\Core\Factory\ProjectionFactoryDependencies;
Expand Down Expand Up @@ -40,21 +41,25 @@ public function build(
$projectionFactoryDependencies->contentRepositoryId
);

$dimensionSpacePointsRepository = new DimensionSpacePointsRepository($this->dbalClient->getConnection(), $tableNamePrefix);

return new ContentGraphProjection(
new DoctrineDbalContentGraphProjection(
$this->dbalClient,
new NodeFactory(
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->nodeTypeManager,
$projectionFactoryDependencies->propertyConverter
$projectionFactoryDependencies->propertyConverter,
$dimensionSpacePointsRepository
),
$projectionFactoryDependencies->contentRepositoryId,
$projectionFactoryDependencies->nodeTypeManager,
new ProjectionContentGraph(
$this->dbalClient,
$tableNamePrefix
),
$tableNamePrefix
$tableNamePrefix,
$dimensionSpacePointsRepository
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function buildSchema(AbstractSchemaManager $schemaManager): Schema
$this->createNodeTable(),
$this->createHierarchyRelationTable(),
$this->createReferenceRelationTable(),
$this->createDimensionSpacePointsTable()
]);
}

Expand All @@ -36,7 +37,6 @@ private function createNodeTable(): Table
$table = new Table($this->tableNamePrefix . '_node', [
DbalSchemaFactory::columnForNodeAnchorPoint('relationanchorpoint')->setAutoincrement(true),
DbalSchemaFactory::columnForNodeAggregateId('nodeaggregateid')->setNotnull(false),
DbalSchemaFactory::columnForDimensionSpacePoint('origindimensionspacepoint')->setNotnull(false),
DbalSchemaFactory::columnForDimensionSpacePointHash('origindimensionspacepointhash')->setNotnull(false),
DbalSchemaFactory::columnForNodeTypeName('nodetypename'),
(new Column('properties', Type::getType(Types::TEXT)))->setNotnull(true)->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION),
Expand All @@ -56,24 +56,31 @@ private function createNodeTable(): Table
private function createHierarchyRelationTable(): Table
{
$table = new Table($this->tableNamePrefix . '_hierarchyrelation', [
(new Column('name', Type::getType(Types::STRING)))->setLength(255)->setNotnull(false)->setCustomSchemaOption('collation', self::DEFAULT_TEXT_COLLATION),
(new Column('name', Type::getType(Types::STRING)))->setLength(255)->setNotnull(false)->setCustomSchemaOption('charset', 'ascii')->setCustomSchemaOption('collation', 'ascii_general_ci'),
dlubitz marked this conversation as resolved.
Show resolved Hide resolved
(new Column('position', Type::getType(Types::INTEGER)))->setNotnull(true),
DbalSchemaFactory::columnForContentStreamId('contentstreamid')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePointHash('dimensionspacepointhash')->setNotnull(true),
DbalSchemaFactory::columnForNodeAnchorPoint('parentnodeanchor'),
DbalSchemaFactory::columnForNodeAnchorPoint('childnodeanchor'),
(new Column('subtreetags', Type::getType(Types::JSON)))->setDefault('{}'),
]);

return $table
->addIndex(['childnodeanchor'])
->addIndex(['contentstreamid'])
->addIndex(['parentnodeanchor'])
->addIndex(['contentstreamid', 'childnodeanchor', 'dimensionspacepointhash'])
->setPrimaryKey(['childnodeanchor', 'contentstreamid', 'dimensionspacepointhash', 'parentnodeanchor'])
->addIndex(['contentstreamid', 'dimensionspacepointhash']);
Comment on lines 68 to 70
Copy link
Member

Choose a reason for hiding this comment

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

lol after debugging i found out that this change here slows down the replay of ContentStreamWasForked events dramatically

Copy link
Member

Choose a reason for hiding this comment

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

I can confirm, this fixes replay for me:
image

I would suggest that we revert that part for now as a "hotfix". Afterwards, we could investigate why that kills the database

Copy link
Member

Choose a reason for hiding this comment

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

See #5009

}

private function createDimensionSpacePointsTable(): Table
{
$table = new Table($this->tableNamePrefix . '_dimensionspacepoints', [
DbalSchemaFactory::columnForDimensionSpacePointHash('hash')->setNotnull(true),
DbalSchemaFactory::columnForDimensionSpacePoint('dimensionspacepoint')->setNotnull(true)
]);

return $table
->setPrimaryKey(['hash']);
}

private function createReferenceRelationTable(): Table
{
$table = new Table($this->tableNamePrefix . '_referencerelation', [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use Doctrine\DBAL\Connection;
use Neos\ContentRepository\Core\DimensionSpace\DimensionSpacePoint;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentRepository\Core\Projection\ContentGraph\NodeTags;
use Neos\ContentRepository\Core\SharedModel\Node\NodeName;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
Expand Down Expand Up @@ -44,16 +45,22 @@ public function __construct(
*/
public function addToDatabase(Connection $databaseConnection, string $tableNamePrefix): void
{
$databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [
'parentnodeanchor' => $this->parentNodeAnchor->value,
'childnodeanchor' => $this->childNodeAnchor->value,
'name' => $this->name?->value,
'contentstreamid' => $this->contentStreamId->value,
'dimensionspacepoint' => $this->dimensionSpacePoint->toJson(),
'dimensionspacepointhash' => $this->dimensionSpacePointHash,
'position' => $this->position,
'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT),
]);
$databaseConnection->transactional(function ($databaseConnection) use (
$tableNamePrefix
) {
$dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix);
$dimensionSpacePoints->insertDimensionSpacePoint($this->dimensionSpacePoint);

$databaseConnection->insert($tableNamePrefix . '_hierarchyrelation', [
'parentnodeanchor' => $this->parentNodeAnchor->value,
'childnodeanchor' => $this->childNodeAnchor->value,
'name' => $this->name?->value,
'contentstreamid' => $this->contentStreamId->value,
'dimensionspacepointhash' => $this->dimensionSpacePointHash,
'position' => $this->position,
'subtreetags' => json_encode($this->subtreeTags, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT),
]);
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
namespace Neos\ContentGraph\DoctrineDbalAdapter\Domain\Projection;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Types\Types;
use Neos\ContentGraph\DoctrineDbalAdapter\Domain\Repository\DimensionSpacePointsRepository;
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues;
use Neos\ContentRepository\Core\NodeType\NodeTypeName;
use Neos\ContentRepository\Core\Projection\ContentGraph\Timestamps;
Expand Down Expand Up @@ -55,7 +57,6 @@ public function updateToDatabase(Connection $databaseConnection, string $tableNa
$tableNamePrefix . '_node',
[
'nodeaggregateid' => $this->nodeAggregateId->value,
'origindimensionspacepoint' => json_encode($this->originDimensionSpacePoint),
'origindimensionspacepointhash' => $this->originDimensionSpacePointHash,
'properties' => json_encode($this->properties),
'nodetypename' => $this->nodeTypeName->value,
Expand Down Expand Up @@ -138,25 +139,38 @@ public static function createNewInDatabase(
?NodeName $nodeName,
Timestamps $timestamps,
): self {
$databaseConnection->insert($tableNamePrefix . '_node', [
'nodeaggregateid' => $nodeAggregateId->value,
'origindimensionspacepoint' => json_encode($originDimensionSpacePoint),
'origindimensionspacepointhash' => $originDimensionSpacePointHash,
'properties' => json_encode($properties),
'nodetypename' => $nodeTypeName->value,
'classification' => $classification->value,
'created' => $timestamps->created,
'originalcreated' => $timestamps->originalCreated,
'lastmodified' => $timestamps->lastModified,
'originallastmodified' => $timestamps->originalLastModified,
], [
'created' => Types::DATETIME_IMMUTABLE,
'originalcreated' => Types::DATETIME_IMMUTABLE,
'lastmodified' => Types::DATETIME_IMMUTABLE,
'originallastmodified' => Types::DATETIME_IMMUTABLE,
]);
$relationAnchorPoint = $databaseConnection->transactional(function ($databaseConnection) use (
$tableNamePrefix,
$nodeAggregateId,
$originDimensionSpacePoint,
$originDimensionSpacePointHash,
$properties,
$nodeTypeName,
$classification,
$timestamps
Comment on lines +143 to +150
Copy link
Member

Choose a reason for hiding this comment

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

i love php

) {
$dimensionSpacePoints = new DimensionSpacePointsRepository($databaseConnection, $tableNamePrefix);
$dimensionSpacePoints->insertDimensionSpacePointByHashAndCoordinates($originDimensionSpacePointHash, $originDimensionSpacePoint);

$databaseConnection->insert($tableNamePrefix . '_node', [
'nodeaggregateid' => $nodeAggregateId->value,
'origindimensionspacepointhash' => $originDimensionSpacePointHash,
'properties' => json_encode($properties),
'nodetypename' => $nodeTypeName->value,
'classification' => $classification->value,
'created' => $timestamps->created,
'originalcreated' => $timestamps->originalCreated,
'lastmodified' => $timestamps->lastModified,
'originallastmodified' => $timestamps->originalLastModified,
], [
'created' => Types::DATETIME_IMMUTABLE,
'originalcreated' => Types::DATETIME_IMMUTABLE,
'lastmodified' => Types::DATETIME_IMMUTABLE,
'originallastmodified' => Types::DATETIME_IMMUTABLE,
]);

$relationAnchorPoint = NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId());
return NodeRelationAnchorPoint::fromInteger((int)$databaseConnection->lastInsertId());
});

return new self(
$relationAnchorPoint,
Expand Down
Loading
Loading