Doctrine orm 条令2查询生成器与实体持久化性能
摘要:更新/刷新实体列表,还是对每个实体运行查询生成器更新,哪个更快? 在ORM(版本2.3)中,我们有以下情况 我们有一张像这样的桌子Doctrine orm 条令2查询生成器与实体持久化性能,doctrine-orm,symfony-2.1,doctrine-query,Doctrine Orm,Symfony 2.1,Doctrine Query,摘要:更新/刷新实体列表,还是对每个实体运行查询生成器更新,哪个更快? 在ORM(版本2.3)中,我们有以下情况 我们有一张像这样的桌子 cow wolf elephant koala 我们想用这个表格对一个虚构农场的报告进行排序。问题是用户希望客户订购动物(如考拉、大象、狼、牛)。现在存在使用CONCAT或CASE向DQL添加权重的可能性(例如0002wolf,0001elephant)。根据我的经验,这要么是很难构建的,当我让它工作时,结果集是一个数组而不是一个集合 因此,为了解决这个问题
cow
wolf
elephant
koala
我们想用这个表格对一个虚构农场的报告进行排序。问题是用户希望客户订购动物(如考拉、大象、狼、牛)。现在存在使用CONCAT或CASE向DQL添加权重的可能性(例如0002wolf,0001elephant)。根据我的经验,这要么是很难构建的,当我让它工作时,结果集是一个数组而不是一个集合
因此,为了解决这个问题,我们为每条记录添加了一个“权重”字段,在运行select之前,我们为每条记录分配了一个权重:
$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个ORDERBY的10表联接。最初,您可以使用名为
日志记录(\doctor\DBAL\LoggingProfiler)的条令实现。我知道这不是更好的答案,但至少您可以实施它,以便为您的每个示例获得最佳结果
namespace Doctrine\DBAL\Logging;
class Profiler implements SQLLogger
{
public $start = null;
public function __construct()
{
}
/**
* {@inheritdoc}
*/
public function startQuery($sql, array $params = null, array $types = null)
{
$this->start = microtime(true);
}
/**
* {@inheritdoc}
*/
public function stopQuery()
{
echo "execution time: " . microtime(true) - $this->start;
}
}
在主条令配置中,您可以启用以下功能:
$logger = new \Doctrine\DBAL\Logging\Profiler;
$config->setSQLLogger($logger);
谢谢你的回答。当我们使用symfony2.1时,我们无论如何都会在dev profiler中获得SQL时间。客户决定无论如何都要使用querybuilder路线。update/rollback方法非常有效。