Siga estas 5 buenas prácticas y aumente la velocidad de su proyecto.

5 sencillos consejos para mejorar el manejo de la base de datos con Symfony2 y Doctrine

Hoy en día, el Mapeo Relacional de Objetos de Doctrine (ORM) es el más utilizado entre los desarrolladores de Symfony porque hace que las cosas entre el desarrollador y la base de datos sean realmente fáciles, aunque existen personas que no están de acuerdo con este punto.

Ya debes saber que Doctrine 2 no se puede comparar con su versión anterior Doctrine 1 en relación al rendimiento, por ejemplo:

  • Doctrine1 implementa el diseño ActiveRecord, mientras que D2 implementa el diseño DataMapper, esa es la diferencia más importante.

  • D2 requiere PHP 5.3 o más reciente y utiliza sus beneficios como espacios de nombres.

  • D2 se divide en un conjunto de subproyectos más pequeños: Doctrine Commons, Doctrine DBAL, Doctrine ORM (para RDBMS) y Doctrine ODM (para MongoDB).

  • D2 es mucho más rápido.

  • D2 admite anotaciones.

Doctrine definitivamente hará la vida más fácil para el programador php.

Lea más sobre aquí  http://stackoverflow.com/questions/4400272/what-are-the-differences-between-doctrine1-and-doctrine2  .

Sin embargo a ti como desarrollador se te anima a ofrecer resultados de buena calidad, el rendimiento de una aplicación da mucho de qué hablar y el desarrollador, aprende algunos consejos para optimizar tu rendimiento con doctrina en tu proyecto symfony2.

1. Evite la hidratación de objetos al manipular muchas entidades

Cuando recupera muchos registros de la base de datos solo para mostrarlos en la vista (por ejemplo, los archivos generados por CRUD predeterminados), debe pensar en no usar la hidratación de objetos predeterminada de Doctrine (devuelve un objeto Doctrine_collection que se traduce en más memoria y consume más tiempo). Incrementa el rendimiento hidratante con los siguientes métodos.

En lugar de recuperar objetos Doctrine_collection asi: 

// In the controller
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Users');
$query = $repo >createQueryBuilder('a')
                ->where('a.role LIKE :role')
                ->setParameter('role', '%ADMIN%');
                
$results = $query->getQuery()->getResult();// Hidratacion por defecto

Aplicar en su lugar:

// In the controller
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Users');
$query = $repo >createQueryBuilder('a')
                ->where('a.role LIKE :role')
                ->setParameter('role', '%ADMIN%');

$results = $query->getQuery()->getArrayResult();// Hydratacion Array

$results = $query->getQuery()->getScalarResult();// Hidratacion Escalar

2. No cargue la entidad completa si puede hacer referencia a ella en persistir

Imaginemos una entidad que tiene un campo al que se hace referencia desde otra tabla de base de datos (un objeto de usuario tiene un rol de campo que tiene una clave externa de la tabla de roles) y para persistir el objeto de usuario necesita que setRole ($ roleObject)  sea ​​una entidad de rol .

En ese caso, hacer una operación de búsqueda adicional ($ id que viene para un parámetro de solicitud, por ejemplo) fuerza a una declaración de base de datos adicional innecesaria (que es lo que todos hacemos para resolver este problema) como esta:

El uso de getReference debe realizarse solo si está seguro del origen de los datos (cuando la memoria caché de su entorno no se borra con frecuencia).

Pero a veces, getReference es útil para, por ejemplo. administrar colecciones más grandes, como acciones, basadas en los ID de los recursos. De esa manera, no tendrá que hacer declaraciones SELECT (find ()) para cada recurso.

// En el controlador

$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Users');
$roleId = 2;
$role = $repo->find($roleId);

$user = new User();
$user->setName('Invisible man');
$user->setAge(27);
$user->setRole($role);
$em->persist($user);
$em->flush();

Gracias a los Proxies de referencia de Doctrine, no tienes que recuperar toda la entidad de la base de datos solo para asociarla con otra como esta:

// En el controlador

$em = $this->getDoctrine()->getManager(); 
$roleId = 2; 

$user = new User(); 
$user->setName('Hombre invisible');
$user->setAge(27); 
$user->setRole($em->getReference('ourcodeworldBundle:Users', $roleId)); 
$em->persist($user); 
$em->flush();

3. No obtengas valores referenciados de entidades en un bucle

Imaginemos una entidad que tiene un campo al que se hace referencia desde otra tabla de base de datos (un objeto de usuario tiene un rol de campo que tiene una clave externa de la tabla de roles) y para persistir el objeto de usuario necesita que  setRole ($ roleObject)  sea ​​una entidad de rol .

Volvemos a la Vista que nos muestra los usuarios, luego vamos a renderizar su nombre, nombre del rol y edad con un bucle de twig como este:

{%for user in collectionUsers %}
<tr>
    <td>{{user.name}}</td>
    <td>{{user.role.name}}</td>{# Ten en cuenta que para cada usuario, se ejecutará UNA CONSULTA solicitando el nombre de su rol !#}
    <td>{{user.age}}</td>
</tr>
{% endfor %}

Entonces, cuando procesa 100 usuarios, desea enviar collectionUsers  como resultado de una consulta de unión y en resultado de matriz, lo que aumentará considerablemente el rendimiento en comparación con la prueba anterior debido a que solo se ejecutará 1 consulta finalmente.

$qb = $this->createQueryBuilder('p');
      $qb->addSelect('a')
        ->innerJoin('p.role', 'a');

return $qb->getQuery()->getArrayResult(); 

4. Varias filas se actualizan mediante la instrucción "actualizar" en lugar de un objeto persistente

 Cuando tiene que actualizar varias entidades, recuperarlas de la base de datos e iterar sobre ellas como entidades ORM se conoce como una práctica realmente mala:

$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Posts');

$newCreatedAt = new \DateTime();
$posts = $repo->findAll();
 
foreach ($posts as $post) {
    $post->setCreatedAt($newCreatedAt);
    $em->persist($post);
}

$em->flush();
 Se recomienda aplicar en su lugar:
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Posts');
$newCreatedAt = new \DateTime();

$qb = $repo->createQueryBuilder('p');
    $qb->update()
        ->set('p.createdAt', ':newCreatedAt')
        ->setParameter('newCreatedAt', $newCreatedAt); 
$qb->getQuery()->execute();

5. Si no es necesario, no cargue todo el objeto (con relaciones) solo para obtener un valor simple

A menos que pueda manejar valores escalares y de matrices, este es un buen consejo para evitar la carga de información innecesaria que solo ocupa espacio en la memoria.

$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ourcodeworldBundle:Users');
$age = $repo->createQuery(
    'SELECT z.age'.
    'FROM ourcodeworldBundle:Users z'.
    'WHERE z.id = :id'
)
->setParameter('id',2)
->getSingleScalarResult();

return $age;// Solamente el numero que necesitamos!

Algunas recomendaciones importantes:

  • Asegúrese de crear correctamente sus consultas.
  • Cargue solo lo que realmente necesita de la base de datos y devuelva si necesita hidratación u objetos.

En el sitio web de la doctrina, alude a un punto importante:

Se recomienda encarecidamente utilizar una caché de código de bytes como APC. Una caché de código de bytes elimina la necesidad de analizar el código PHP en cada solicitud y puede mejorar enormemente el rendimiento.

“Si le importa el rendimiento y no usa una caché de código de bytes, entonces realmente no le importa el rendimiento. Consiga uno y comience a usarlo ".

Stas Malyshev, colaborador principal de PHP y empleado de Zend

Finalmente, aplique cuidadosamente este artículo a sus proyectos. No es necesario que atienda todas estas recomendaciones si su proyecto no maneja mucho tráfico, consultas pesadas o tiene especificaciones bajas.


Ingeniero de Software Senior en EPAM Anywhere. Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores