Doctrine korzysta z Mapy tożsamości wzór do śledzenia obiektów. Tak więc za każdym razem, gdy pobierasz obiekt z bazy danych, Doctrine przechowuje odniesienie do tego obiektu w swojej UnitOfWork. I zasadniczo używa identyfikatora jako klucza do zarządzania obiektami wewnątrz swojego UnitOfWork.
Np.
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
uruchomiłoby tylko jedno zapytanie SELECT w bazie danych. W drugim wywołaniu doktryna sprawdzi mapę tożsamości i znajdzie ten sam identyfikator bez wykonywania objazdu bazy danych. Nawet jeśli użyjesz obiektu proxy, obiekt będzie miał ten sam identyfikator.
Ale dla
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
w dzienniku SQL zobaczysz dwa zapytania, mimo że odwołujesz się do tego samego obiektu. Doctrine zna obiekty tylko według identyfikatora , więc zapytanie o inne kryteria musi trafić do bazy danych, nawet jeśli zostało wcześniej wykonane.
Ale doktryna jest sprytna, nie tworzy nowego bytu, ale otrzymuje identyfikator i sprawdza, czy jest już w pamięci.
PHP postępuje zgodnie z paradygmatem copy-on-write, jest to zasada optymalizacji. Prawdziwa kopia zmiennej jest tworzona tylko wtedy, gdy zmienna jest modyfikowana. Tak więc użycie pamięci dla żądania, które odczytuje obiekty z bazy danych, jest takie samo, jak gdyby nie przechowywać kopii zmiennej.
Tak więc tylko wtedy, gdy zmieniasz zmienne, aplikacje tworzą wewnętrznie nowe zmienne i zużywają pamięć.
Więc kiedy zadzwonisz flush , doktryna iteruje po Mapie Tożsamości i porównuje oryginalną właściwość każdego obecjts z bieżącymi wartościami. W przypadku wykrycia zmian zostanie on umieszczony w kolejce na zapytanie UPDATE. Tylko aktualnie zaktualizowane pola są zmieniane w bazie danych.
Jak zoptymalizować
Czasami więc ma sens oznaczenie obiektów jako tylko do odczytu (tylko wstawianie i usuwanie), aby nie znajdowały się w zestawie zmian (możesz to zrobić w swoim pliku mapowania xml lub z adnotacjami lub w kodzie php).
$entityManager->getUnitOfWork()->markReadOnly($entity)
Lub opróżnij tylko jedną jednostkę
$entityManager->flush($entity)