Doctrineはアイデンティティマップを使用します オブジェクトを追跡するためのパターン。したがって、データベースからオブジェクトをフェッチするときはいつでも、DoctrineはそのUnitOfWork内にこのオブジェクトへの参照を保持します。そして基本的には、UnitOfWork内のオブジェクトを管理するためのキーとしてIDを使用します。
例:
$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);
データベースに対して1つのSELECTクエリのみを実行します。 2番目の呼び出しでは、DoctrineはIDマップをチェックし、データベースのラウンドトリップを実行せずに同じIDを見つけます。プロキシオブジェクトを使用する場合でも、オブジェクトは同じIDを持ちます。
しかし
$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));
同じオブジェクトを参照しているにもかかわらず、SQLログに2つのクエリが表示されます。 DoctrineはIDでのみオブジェクトを認識します 、したがって、以前に実行された場合でも、別の条件のクエリはデータベースに送信する必要があります。
しかし、教義は賢く、新しいエンティティを作成するのではなく、IDを取得し、それがメモリ内で正常であるかどうかを確認します。
PHPは、コピーオンライトのパラダイムに従います。これは最適化の原則です。変数の実際のコピーは、変数が変更された場合にのみ作成されます。したがって、データベースからオブジェクトを読み取るリクエストのメモリ使用量は、変数のコピーを保持しない場合と同じです。
したがって、変数を変更した場合にのみ、アプリケーションは内部で新しい変数を作成し、メモリを消費します。
したがって、フラッシュを呼び出すと 、doctrineはIdentiy Mapを反復処理し、各obecjtsの元のプロパティを現在の値と比較します。変更が検出されると、UPDATEクエリのキューに入れられます。データベースでは、実際に更新されたフィールドのみが変更されます。
最適化する方法
そのため、オブジェクトを読み取り専用(挿入と削除のみ)としてマークすることが理にかなっている場合があります。これにより、オブジェクトはチェンジセットに含まれなくなります(xmlマッピングファイル、注釈、またはphpコードで行うことができます)。
$entityManager->getUnitOfWork()->markReadOnly($entity)
または、1つのエンティティのみをフラッシュします
$entityManager->flush($entity)