sql >> Base de Datos >  >> RDS >> Mysql

Doctrine2 en Symfony2:¿Cómo puedo ver qué llamada de objeto conduce a una consulta?

Doctrine usa el mapa de identidad patrón para rastrear objetos. Entonces, cada vez que obtienes un objeto de la base de datos, Doctrine mantiene una referencia a este objeto dentro de su UnitOfWork. Y básicamente usa la ID como clave para administrar objetos dentro de su UnitOfWork.

Por ejemplo

$objectA = $this->entityManager->find('EntityName', 1);
$objectB = $this->entityManager->find('EntityName', 1);

dispararía solo una consulta SELECT contra la base de datos. En la segunda llamada, la doctrina verificará el mapa de identidad y encontrará la misma ID sin hacer un viaje de ida y vuelta a la base de datos. Incluso si usa un objeto proxy, el objeto tendría la misma ID.

Pero para

$objectA = $repository->findOneBy(array('name' => 'Benjamin'));
$objectB = $repository->findOneBy(array('name' => 'Benjamin'));

vería dos consultas en su registro SQL, a pesar de que hace referencia al mismo objeto. Doctrine solo reconoce objetos por ID , por lo que una consulta para un criterio diferente tiene que ir a la base de datos, incluso si se ejecutó antes.

Pero la doctrina es inteligente, no crea una nueva entidad sino que obtiene la identificación y mira si ya está en la memoria.

PHP sigue el paradigma copy-on-write, es un principio de optimización. Una copia real de una variable solo se realiza cuando se modifica la variable. Entonces, el uso de memoria para una solicitud que lee objetos de la base de datos es el mismo que si no se mantuviera una copia variable.

Entonces, solo cuando cambia las variables, sus aplicaciones crean nuevas variables internamente y consumen memoria.

Así que cuando llamas a flush , la doctrina itera sobre el Identiy Map y compara la propiedad original de cada obecjts con los valores actuales. Si se detectan cambios, se pondrá en cola para una consulta de ACTUALIZACIÓN. Solo los campos actualizados se modifican en la base de datos.

Cómo optimizar

Entonces, a veces tiene sentido marcar objetos como de solo lectura (solo insertar y eliminar), para que no estén en el conjunto de cambios (puede hacerlo en su archivo de mapeo xml o con anotaciones o en su código php).

$entityManager->getUnitOfWork()->markReadOnly($entity)

O vaciar solo una entidad

$entityManager->flush($entity)