Symfony1 在数据库中存储行顺序的优化解决方案
我在条令/symfony中有一个数据模型。我有一门“课程”,有很多“课程”。对于每个课程,我需要计算课程出现的顺序(按日期)。例如,“Java For初学者”课程在10月份可能有10节课,我需要检索这些课程的顺序,以便第一节课被称为“Java For初学者1”,等等 目前,我的课程模型中有一个getTitle()方法,用于查询数据库以确定数字。这个很好用。然而,当屏幕上有400个课程(这是一个典型的用例)时,会产生400多个查询 我已经阅读了有关条令行为的内容,据我所知,每次添加、编辑或删除课程时,我都可以添加一个行为,我可以重新计算所有序列号,并将其存储在数据库中。然而,我无法让它有效地工作 有没有比我刚才提到的更有效的方法 干杯 马特 上面的代码返回我的所有课程信息(除了课程号)Symfony1 在数据库中存储行顺序的优化解决方案,symfony1,doctrine,Symfony1,Doctrine,我在条令/symfony中有一个数据模型。我有一门“课程”,有很多“课程”。对于每个课程,我需要计算课程出现的顺序(按日期)。例如,“Java For初学者”课程在10月份可能有10节课,我需要检索这些课程的顺序,以便第一节课被称为“Java For初学者1”,等等 目前,我的课程模型中有一个getTitle()方法,用于查询数据库以确定数字。这个很好用。然而,当屏幕上有400个课程(这是一个典型的用例)时,会产生400多个查询 我已经阅读了有关条令行为的内容,据我所知,每次添加、编辑或删除课程
Doctrine\u查询::create()
->选择('计数(l.id)作为计数')
->从('l课')
->leftJoin('l.Course c')
->其中('c.id=?',$this->course\u id)
->andWhere('TIMESTAMP(l.date,l.time)<?',$this->date'.$this->time)
->orderBy('l.date,l.time');
$lessons=$q->fetchOne();
返回$lessons->count+1;
这段代码作为函数存在于课程模型中。它计算给定课程的序号,并将其作为整数返回。这是一个被调用400多次的方法。我尝试将其作为子查询添加到第一个查询中,但没有成功
行为准则
public function postInsert(条令事件$Event){
$invoker=$event->getInvoker();
$table=条令::getTable('Lesson');
//课程查询
$cq=Doctrine::getTable('Lesson')->createQuery();
$cq->选择('计数(l.id)作为计数')
->从('l课')
->leftJoin('l.Course c')
->其中('c.id=?',$invoker->Course->id)
->andWhere('TIMESTAMP(l.date,l.time)<?',$invoker->date'.$invoker->time)
->orderBy('l.date,l.time');
$lessons=$cq->fetchOne();
$q=$table->createQuery();
$q->update()->
设置('序列号',$LESSIONS->count+1)->
其中('id=?',$invoker->id)->
执行();
}
这里明显的问题是,它只更新调用的课程。如果一个课程更新其序列,则所有课程都应更新其序列号。但是,当我试图从我的装置中填充数据库时,上面的代码会导致内存问题(大约5000节课,在大约1500节时失败)。编辑::
你的内存正在耗尽,因为你用这些东西消耗了大量的内存。您应该尝试以1000人为一组进行批处理(因为您在1500人左右时失败)
您可以做的另一件事不是直接将侦听器/行为放在模型上,而是创建一个postTransactionCommit
侦听器。在这个侦听器中,您可以检查课程
表中是否有任何记录是提交的一部分,然后用正确的顺序更新它们
编辑: 所以根据我们的评论。。。让我们转到另一个方向:
Doctrine_Core::getTable('Course')->createQuery('c')
->leftJoin('l.Lesson')
->orderBy('l.date_column')
->execute();
通常,为了避免额外的查询,您会在查询中执行join,这样您就不会有额外的开销。例如:
Doctrine_Core::getTable('Lesson')->createQuery('l')
->leftJoin('l.Course')
->orderBy('l.date_column')
->execute();
通过这种方式,课程和课程信息将在一次查询中记录下来,课程将随课程一起补充水分
当然,这对序列号没有任何影响。这真的是一个不同的问题,我认为最好的办法是按照你自己的建议使用一种行为。如果您想发布您的行为代码和问题描述,我相信我们可以帮助您谢谢您的回答。课程的序列号依赖于给定课程的所有课程,因此连接必须先拉入课程,然后拉入所有课程-这样更有效吗?我会添加一些代码来帮助我解释。谢谢你的帮助。我想我已经决定了一种行为是前进的方向——不必在用户每次观看课程时计算序列号(这将是很多)。我将尝试实现一个,并从那里开始。
public function postInsert(Doctrine_Event $event) {
$invoker = $event->getInvoker();
$table = Doctrine::getTable('Lesson');
// Course query
$cq = Doctrine::getTable('Lesson')->createQuery();
$cq->select('COUNT(l.id) as count')
->from('Lesson l')
->leftJoin('l.Course c')
->where('c.id = ?', $invoker->Course->id)
->andWhere('TIMESTAMP(l.date, l.time) < ?', $invoker->date . ' ' . $invoker->time)
->orderBy('l.date, l.time');
$lessons = $cq->fetchOne();
$q = $table->createQuery();
$q->update()->
set('sequence_number', $lessons->count + 1)->
where('id = ?', $invoker->id)->
execute();
}
Doctrine_Core::getTable('Course')->createQuery('c')
->leftJoin('l.Lesson')
->orderBy('l.date_column')
->execute();
Doctrine_Core::getTable('Lesson')->createQuery('l')
->leftJoin('l.Course')
->orderBy('l.date_column')
->execute();