Doctrine gebruikt de Identiteitskaart patroon om objecten te volgen. Dus wanneer u een object uit de database ophaalt, bewaart Doctrine een verwijzing naar dit object in zijn UnitOfWork. En eigenlijk gebruikt het de ID als een sleutel om objecten binnen zijn UnitOfWork te beheren.
Bijv.
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
zou slechts één SELECT-query op de database afvuren. Bij de tweede oproep zal de doctrine de identiteitskaart controleren en dezelfde ID vinden zonder een database-rondreis te doen. Zelfs als u een proxy-object gebruikt, heeft het object dezelfde ID.
Maar voor
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
u zou twee query's in uw SQL-logboek zien, ondanks het feit dat u naar hetzelfde object verwijst. De leer kent alleen objecten op ID , dus een query voor een ander criterium moet naar de database gaan, zelfs als deze eerder is uitgevoerd.
Maar doctrine is slim, het creëert geen nieuwe entiteit maar krijgt de ID en kijkt of het al in het geheugen staat.
PHP volgt het copy-on-write paradigma, het is een optimalisatieprincipe. Een echte kopie van een variabele wordt pas gemaakt als de variabele wordt gewijzigd. Dus het geheugengebruik voor een verzoek dat objecten uit de database leest, is hetzelfde als om een variabele kopie niet te bewaren.
Dus alleen wanneer u variabelen wijzigt, creëert uw applicatie intern nieuwe variabelen en verbruikt het geheugen.
Dus als je flush roept , de doctrine herhaalt de identiteitskaart en vergelijkt de oorspronkelijke eigenschap van elk object met de huidige waarden. Als er wijzigingen worden gedetecteerd, wordt deze in de wachtrij geplaatst voor een UPDATE-query. Alleen daadwerkelijk bijgewerkte velden worden gewijzigd in de database.
Hoe te optimaliseren
Dus soms is het logisch om objecten te markeren als alleen-lezen (alleen invoegen en verwijderen), zodat ze niet in de wijzigingenset staan (je kunt het doen in je xml-toewijzingsbestand of met annotaties of in je php-code).
$entityManager->getUnitOfWork()->markReadOnly($entity)
Of spoel slechts één entiteit door
$entityManager->flush($entity)