Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Doctrine2 no Symfony2:Como posso ver qual chamada de objeto leva a uma consulta?


O Doctrine usa o Mapa de Identidade padrão para rastrear objetos. Então sempre que você busca um objeto do banco de dados, o Doctrine mantém uma referência a este objeto dentro de sua UnitOfWork. E basicamente ele usa o ID como chave para gerenciar objetos dentro de sua UnitOfWork.

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

dispararia apenas uma consulta SELECT no banco de dados. Na segunda chamada, a doutrina verificará o mapa de identidade e encontrará o mesmo ID sem fazer uma viagem de ida e volta ao banco de dados. Mesmo se você usar o objeto proxy, o objeto terá o mesmo ID.

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

você veria duas consultas em seu log SQL, apesar do fato de fazer referência ao mesmo objeto. O Doctrine só conhece objetos por ID , portanto, uma consulta para um critério diferente deve ir para o banco de dados, mesmo que tenha sido executada antes.

Mas a doutrina é inteligente, não cria uma nova entidade, mas pega o ID e verifica se já está na memória.

PHP segue o paradigma copy-on-write, é um princípio de otimização. Uma cópia real de uma variável só é feita quando a variável é modificada. Portanto, o uso de memória para uma solicitação que lê objetos do banco de dados é o mesmo que não manter uma cópia de variável.

Portanto, somente quando você altera as variáveis, seus aplicativos criam novas variáveis ​​internamente e consomem memória.

Então, quando você chama flush , a doutrina itera sobre o Mapa de Identidade e compara a propriedade original de cada objeto com os valores atuais. Se forem detectadas alterações, ele entrará na fila para uma consulta UPDATE. Somente os campos realmente atualizados são alterados no banco de dados.

Como otimizar

Então, às vezes, faz sentido marcar objetos como somente leitura (apenas inserir e remover), para que eles não estejam no changeset (você pode fazer isso em seu arquivo de mapeamento xml ou com anotações ou em seu código php).
$entityManager->getUnitOfWork()->markReadOnly($entity)

Ou liberar apenas uma entidade
$entityManager->flush($entity)