检索 doctrine 中 table 的所有行
Retrieve all rows from table in doctrine
我有 table 超过 100 000 行,我想 select 所有这些都在教义中并对每一行做一些操作,在 symfony2 中我尝试用教义来做此查询:
$query = $this->getDefaultEntityManager()
->getRepository('AppBundle:Contractor')
->createQueryBuilder('c')
->getQuery()->iterate();
foreach ($query as $contractor) {
// doing something
}
但后来我得到内存泄漏,因为我认为它将所有数据写入内存。
我在 ADOdb 方面有更多经验,在我这样做的时候在那个库中:
$result = $ADOdbObject->Execute('SELECT * FROM contractors');
while ($arrRow = $result->fetchRow()) {
// do some action
}
我没有发现任何内存泄漏。
那么如何 select 来自 table 的所有数据并且在 symfony2 中不发生内存泄漏?
Question EDIT
当我尝试删除 foreach 并进行迭代时,我也遇到内存泄漏:
$query = $this->getDefaultEntityManager()
->getRepository('AppBundle:Contractor')
->createQueryBuilder('c')
->getQuery()->iterate();
尝试使用这种方法:
foreach ($query as $contractor) {
// doing something
$this->getDefaultEntityManager()->detach($contractor);
$this->getDefaultEntityManager()->clear($contractor);
unset($contractor); // tell to the gc the object is not in use anymore
}
希望对您有所帮助
如果你真的需要获取所有的记录,我建议你直接使用database_connection。查看它的界面并选择不会将所有数据加载到内存中(并且不会将记录映射到您的实体)的方法。
你可以使用这样的东西(假设这段代码在控制器中):
$db = $this->get('database_connection');
$query = 'select * from <your_table>';
$sth = $db->prepare($query);
$sth->execute();
while($row = $sth->fetch()) {
// some stuff
}
可能这不是您所需要的,因为您可能希望在处理完所有集合后拥有对象。但也许您不需要这些对象。反正想想这个。
正常的做法是使用iterate().
$q = $this->getDefaultEntityManager()->createQuery('select u from AppBundle:Contractor c');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
// do something
}
但是,正如学说文档所说,这仍然会导致错误。
Results may be fully buffered by the database client/ connection allocating additional memory not visible to the PHP process. For large sets this may easily kill the process for no apparant reason.
最简单的方法是简单地创建具有偏移量和限制的较小查询。
//get the count of the whole query first
$qb = $this->getDefaultEntityManager();
$qb->select('COUNT(u)')->from('AppBundle:Contractor', 'c');
$count = $qb->getQuery()->getSingleScalarResult();
//lets say we go in steps of 1000 to have no memory leak
$limit = 1000;
$offset = 0;
//loop every 1000 > create a query > loop the result > repeat
while ($offset < $count){
$qb->select('u')
->from('AppBundle:Contractor', 'c')
->setMaxResults($limit)
->setFirstResult($offset);
$result = $qb->getQuery()->getResult();
foreach ($result as $contractor) {
// do something
}
$offset += $limit;
}
对于如此繁重的数据集,这很可能会超过 最大执行时间 ,默认情况下为 30 秒 。因此,请确保在 php.ini 中手动更改 set_time_limit。如果您只想更新具有已知模式的所有数据集,您应该考虑编写一个大的更新查询,而不是在 PHP.
中循环和编辑结果
我有 table 超过 100 000 行,我想 select 所有这些都在教义中并对每一行做一些操作,在 symfony2 中我尝试用教义来做此查询:
$query = $this->getDefaultEntityManager()
->getRepository('AppBundle:Contractor')
->createQueryBuilder('c')
->getQuery()->iterate();
foreach ($query as $contractor) {
// doing something
}
但后来我得到内存泄漏,因为我认为它将所有数据写入内存。
我在 ADOdb 方面有更多经验,在我这样做的时候在那个库中:
$result = $ADOdbObject->Execute('SELECT * FROM contractors');
while ($arrRow = $result->fetchRow()) {
// do some action
}
我没有发现任何内存泄漏。
那么如何 select 来自 table 的所有数据并且在 symfony2 中不发生内存泄漏?
Question EDIT
当我尝试删除 foreach 并进行迭代时,我也遇到内存泄漏:
$query = $this->getDefaultEntityManager()
->getRepository('AppBundle:Contractor')
->createQueryBuilder('c')
->getQuery()->iterate();
尝试使用这种方法:
foreach ($query as $contractor) {
// doing something
$this->getDefaultEntityManager()->detach($contractor);
$this->getDefaultEntityManager()->clear($contractor);
unset($contractor); // tell to the gc the object is not in use anymore
}
希望对您有所帮助
如果你真的需要获取所有的记录,我建议你直接使用database_connection。查看它的界面并选择不会将所有数据加载到内存中(并且不会将记录映射到您的实体)的方法。
你可以使用这样的东西(假设这段代码在控制器中):
$db = $this->get('database_connection');
$query = 'select * from <your_table>';
$sth = $db->prepare($query);
$sth->execute();
while($row = $sth->fetch()) {
// some stuff
}
可能这不是您所需要的,因为您可能希望在处理完所有集合后拥有对象。但也许您不需要这些对象。反正想想这个。
正常的做法是使用iterate().
$q = $this->getDefaultEntityManager()->createQuery('select u from AppBundle:Contractor c');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
// do something
}
但是,正如学说文档所说,这仍然会导致错误。
Results may be fully buffered by the database client/ connection allocating additional memory not visible to the PHP process. For large sets this may easily kill the process for no apparant reason.
最简单的方法是简单地创建具有偏移量和限制的较小查询。
//get the count of the whole query first
$qb = $this->getDefaultEntityManager();
$qb->select('COUNT(u)')->from('AppBundle:Contractor', 'c');
$count = $qb->getQuery()->getSingleScalarResult();
//lets say we go in steps of 1000 to have no memory leak
$limit = 1000;
$offset = 0;
//loop every 1000 > create a query > loop the result > repeat
while ($offset < $count){
$qb->select('u')
->from('AppBundle:Contractor', 'c')
->setMaxResults($limit)
->setFirstResult($offset);
$result = $qb->getQuery()->getResult();
foreach ($result as $contractor) {
// do something
}
$offset += $limit;
}
对于如此繁重的数据集,这很可能会超过 最大执行时间 ,默认情况下为 30 秒 。因此,请确保在 php.ini 中手动更改 set_time_limit。如果您只想更新具有已知模式的所有数据集,您应该考虑编写一个大的更新查询,而不是在 PHP.
中循环和编辑结果