5 простых советов по улучшению обработки базы данных с помощью Symfony2 и Doctrine

В настоящее время реляционное сопоставление объектов Doctrine (ORM) наиболее широко используется разработчиками Symfony, поскольку упрощает взаимодействие между разработчиком и базой данных, хотя существуют люди, которые не согласны с этим.

Вы уже должны знать, что Doctrine 2 нельзя сравнивать с его старой версией Doctrine 1 в отношении производительности, например:

  • Doctrine1 реализует дизайн ActiveRecord, в то время как D2 реализует дизайн DataMapper — это самое важное отличие.

  • D2 требует PHP 5.3 или новее и использует его преимущества, такие как пространства имен.

  • D2 разделен на набор более мелких подпроектов: Doctrine Commons, Doctrine DBAL, Doctrine ORM (для RDBMS) и Doctrine ODM (для MongoDB).

  • D2 намного быстрее.

  • D2 поддерживает аннотации.

Доктрина определенно облегчит жизнь программисту php.

Подробнее о здесь http://stackoverflow.com/questions/4400272/what-are-the-differences-between-doctrine1-and-doctrine2 .

Тем не менее, вам, как разработчику, предлагается предлагать качественные результаты, производительность приложения дает много, чтобы поговорить об этом и о разработчике, узнать несколько советов по оптимизации вашей работы с помощью доктрины в вашем проекте symfony2.

1. Избегайте гидратации объектов при работе со многими объектами.

Когда вы извлекаете много регистров из базы данных только для их отображения в представлении (например, файлы, сгенерированные CRUD по умолчанию), вам следует подумать о том, чтобы не использовать стандартное увлажнение объекта Doctrine (возвращает Doctrine_collection объект, что переводится в больше памяти и времени). Повысьте эффективность увлажнения с помощью следующих методов.

Вместо извлечения Doctrine_collection объекты лайк :

// 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();// Default hydration

Применить вместо:

// 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();// Array hydration
$results = $query->getQuery()->getScalarResult();// Scalar hydration

2. Не загружайте всю сущность, если вы можете ссылаться на нее при сохранении

Давайте представим сущность, у которой есть поле, на которое ссылается другая таблица базы данных (объект User имеет поле Role, имеющее внешний ключ из таблицы Role), и для сохранения нужного вам пользовательского объекта setRole ($ roleObject) быть ролью

В этом случае выполнение дополнительной операции поиска (например, $ id для параметра запроса) приводит к ненужному дополнительному оператору базы данных (что мы и делаем для решения этой проблемы) следующим образом:

Использование getReference должно выполняться только в том случае, если вы уверены в происхождении данных (когда кэш вашей среды не очищается часто).

Но иногда getReference удобно, например. управлять большими коллекциями, такими как действия, на основе идентификаторов ресурсов. Таким образом, вам не нужно будет делать операторы SELECT (find ()) для каждого ресурса.

// In the controller
$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();

Благодаря ссылочным прокси доктрины вам не нужно извлекать всю сущность из базы данных только для того, чтобы связать ее с другой, такой как эта:

// In the controller
$em = $this->getDoctrine()->getManager();
$roleId = 2;
$user = new User();
$user->setName('Invisible man');
$user->setAge(27);
$user->setRole($em->getReference('ourcodeworldBundle:Users', $roleId));
$em->persist($user);
$em->flush();

3. Не получать ссылочные значения от сущностей в цикле

Давайте представим сущность, у которой есть поле, на которое ссылается другая таблица базы данных (объект User имеет поле Role, имеющее внешний ключ из таблицы Role), и для сохранения нужного вам пользовательского объекта setRole ($ roleObject) быть ролью

Мы вернемся к представлению, которое показывает нам пользователей, затем мы будем отображать его имя, имя роли и возраст с помощью цикла веточек, например:

{%for user in collectionUsers %}

{{user.name}}
{{user.role.name}}{# Keep in mind that for every user , A QUERY will be executed asking for the name of its role !#}
{{user.age}}

{%endfor%}

Поэтому, когда вы отображаете 100 пользователей, вы хотите отправить collectionUsers В результате запроса соединения и результата массива это значительно повысит производительность по сравнению с предыдущим тестом, поскольку в итоге будет выполнен только один запрос.

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

4. Обновление нескольких строк с использованием оператора update вместо сохранения объекта

Когда вам нужно обновить несколько объектов, извлеченных из базы данных и повторяющих их как объекты ORM, это очень плохая практика

$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();

Рекомендуется применять вместо:

$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. Если нет необходимости, не загружайте весь объект (с отношениями) только для получения простого значения

Если вы не можете работать со скалярными значениями и значениями массивов, это хороший совет, чтобы предотвратить загрузку ненужной информации, которая занимает только место в памяти.

$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;//Just the number we need !

Некоторые важные рекомендации:

  • Убедитесь, что вы правильно создаете свои запросы.
  • Загрузите только то, что вам действительно нужно, из базы данных и верните, что вам нужны гидратации или объекты.

На веб-сайте доктрины упоминается важный момент:

Настоятельно рекомендуется использовать кэш байт-кода, такой как APC. Кэш байт-кода устраняет необходимость разбора PHP-кода при каждом запросе и может значительно повысить производительность.

«Если вы заботитесь о производительности и не используете кеш байт-кода, то вам не очень важна производительность. Пожалуйста, получите и начните использовать его. ”

Стас Малышев, основной участник PHP и сотрудник Zend

Наконец, внимательно следите за тем, чтобы эта статья была применима к вашим проектам. Необязательно выполнять все эти рекомендации, если ваш проект не обрабатывает очень большой трафик, большие запросы или низкие спецификации.

Ссылка на основную публикацию
Adblock
detector