요약 : 엔티티 목록을 업데이트/플러시하거나 각각에 대해 쿼리 빌더 업데이트를 실행하는 것이 더 빠릅니까?Doctrine 2 쿼리 빌더 대 엔티티 지속 성능
Doctrine ORM (버전 2.3)에는 다음과 같은 상황이 있습니다.
우리는이
cow
wolf
elephant
koala
과 같은 테이블을 가지고 있고 우리는 가상 농장의 보고서를 정렬이 표를 사용하고 싶습니다. 문제는 고객이 동물 주문 (예 : 코알라, 코끼리, 늑대, 암소)을하고 싶어한다는 것입니다. 이제 CONCAT 또는 CASE를 사용하여 DQL에 가중치를 추가 할 수 있습니다 (예 : 0002wolf, 0001elephant). 내 경험에 의하면 이것은 빌드하기 까다 롭습니다. 결과 세트는 배열이 아니고 콜렉션이었습니다. 이것은 완벽하게 작동
$animals = $em->getRepository('AcmeDemoBundle:Animal')->findAll();
foreach ($animals as $animal) {
if ($animal->getName() == 'koala') {
$animal->setWeight(1);
} else if ($animal->getName() == 'elephant') {
$animal->setWeight(2);
}
// etc
$em->persist($animal);
}
$em->flush();
$query = $em->createQuery(
'SELECT c FROM AcmeDemoBundle:Animal c ORDER BY c.weight'
);
:
그래서,이 문제를 해결하기 위해 우리는 선택을 실행하기 전에, 우리는 무게 각각을 할당, 각 레코드에 "무게"필드를 추가합니다. 경쟁 조건을 피하기 위해 다음을 트랜잭션 블록에 추가했습니다.$em->getConnection()->beginTransaction();
// code from above
$em->getConnection()->rollback();
동일한 보고서를 생성하는 여러 사용자를 처리 할 때 훨씬 더 강력합니다.
$em->getConnection()->beginTransaction();
$qb = $em->createQueryBuilder();
$q = $qb->update('AcmeDemoBundle:Animal', 'c')
->set('c.weight', $qb->expr()->literal(1))
->where('c.name = ?1')
->setParameter(1, 'koala')
->getQuery();
$p = $q->execute();
$qb = $em->createQueryBuilder();
$q = $qb->update('AcmeDemoBundle:Animal', 'c')
->set('c.weight', $qb->expr()->literal(2))
->where('c.name = ?1')
->setParameter(1, 'elephant')
->getQuery();
$p = $q->execute();
// etc
$query = $em->createQuery(
'SELECT c FROM AcmeDemoBundle:Animal c ORDER BY c.weight'
);
$em->getConnection()->rollback();
질문 :
1) 두 예제의 더 나은 성능을 것을 또는 엔티티는 다음과 같이 가중 될 수있다?
2) 결과적으로 컬렉션이 필요하다는 것을 염두에 두어야 할 더 좋은 방법이 있습니까?
메모리에있는 결과 집합을 정렬하는 옵션이 아니므로 데이터베이스 수준에서 수행해야합니다. 실제 문은 5 개의 orderbys가있는 10 개의 테이블 조인입니다.
감사합니다. 우리는 Symfony 2.1을 사용하면서 dev 프로파일 러에서 SQL 시간을 얻습니다. 고객이 어쨌든 querybuilder 경로를 원한다고 결정했습니다. 업데이트/롤백 방법이 완벽하게 작동합니다. – mogoman
음, 어쨌든 환영합니다 :) – manix