Skip to content

Commit 116cdf8

Browse files
committed
#11977 implemented simplistic (and ugly) batch handing of INSERT operations in UnitOfWork#executeInserts()
This logic also brings a minor benefit in reducing the number of times `ListenersInvoker#getSubscribedSystems` is queried. TODOs: * [ ] integration test this - it is expected to reduce the number of `EntityPersister#executeInserts()` calls * [ ] refactor this by creating a new `@internal` class for the batch, and perhaps batch via a generator * [ ] reduce amount of repeated `getClassMetadata()` calls * [ ] reduce overall size of `UnitOfWork` code, instead of increasing it
1 parent 05c8c5f commit 116cdf8

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

src/UnitOfWork.php

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
use function array_sum;
6262
use function array_values;
6363
use function assert;
64+
use function count;
6465
use function current;
6566
use function get_debug_type;
6667
use function implode;
@@ -1039,28 +1040,60 @@ private function executeInserts(): void
10391040
{
10401041
$entities = $this->computeInsertExecutionOrder();
10411042
$eventsToDispatch = [];
1043+
// @TODO #11977 this is ugly and to be tested: making it work, then refactoring later.
1044+
// We assemble micro-batches to process together: this should probably occur in a `private` function?
1045+
// @TODO #11977 test this by verifying the number of executed SQL queries in a flush operation?
1046+
// @TODO #11977 could this be applied also to batch updates? If so, let's raise a new issue.
1047+
/** @var list<array{class: Mapping\ClassMetadata, entities: non-empty-list<object>}> $batchedByType */
1048+
$batchedByType = [];
10421049

10431050
foreach ($entities as $entity) {
1044-
$oid = spl_object_id($entity);
1045-
$class = $this->em->getClassMetadata($entity::class);
1051+
$currentClass = ($batchedByType[count($batchedByType) - 1]['class'] ?? null)?->getName();
1052+
$entityClass = $this->em->getClassMetadata($entity::class);
1053+
1054+
if (
1055+
$currentClass !== $entityClass->name
1056+
// don't batch things together, if an ID generator is needed
1057+
|| $entityClass->idGenerator->isPostInsertGenerator()
1058+
) {
1059+
$batchedByType[] = [
1060+
'class' => $entityClass,
1061+
'entities' => [$entity],
1062+
];
1063+
1064+
continue;
1065+
}
1066+
1067+
$batchedByType[count($batchedByType) - 1]['entities'][] = $entity;
1068+
}
1069+
1070+
foreach ($batchedByType as $batch) {
1071+
$class = $batch['class'];
1072+
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist);
10461073
$persister = $this->getEntityPersister($class->name);
10471074

1048-
$persister->addInsert($entity);
1075+
foreach ($batch['entities'] as $entity) {
1076+
$oid = spl_object_id($entity);
1077+
1078+
$persister->addInsert($entity);
10491079

1050-
unset($this->entityInsertions[$oid]);
1080+
unset($this->entityInsertions[$oid]);
1081+
}
10511082

10521083
$persister->executeInserts();
10531084

1054-
if (! isset($this->entityIdentifiers[$oid])) {
1055-
//entity was not added to identity map because some identifiers are foreign keys to new entities.
1056-
//add it now
1057-
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
1058-
}
1085+
foreach ($batch['entities'] as $entity) {
1086+
$oid = spl_object_id($entity);
10591087

1060-
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist);
1088+
if (! isset($this->entityIdentifiers[$oid])) {
1089+
//entity was not added to identity map because some identifiers are foreign keys to new entities.
1090+
//add it now
1091+
$this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity);
1092+
}
10611093

1062-
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
1063-
$eventsToDispatch[] = ['class' => $class, 'entity' => $entity, 'invoke' => $invoke];
1094+
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
1095+
$eventsToDispatch[] = ['class' => $class, 'entity' => $entity, 'invoke' => $invoke];
1096+
}
10641097
}
10651098
}
10661099

0 commit comments

Comments
 (0)