Doctrine orm 如何处理大型条令集合和关联

Doctrine orm 如何处理大型条令集合和关联,doctrine-orm,symfony,Doctrine Orm,Symfony,我正在做一个项目,我必须从数据库中收集大量数据。我使用Symfony2(symfony bf1281aebdc842a39ec0eb7438e1ea3fca9b9705)和Doctrine2(doctrine 3B3186EE98392802A44118CD421A353119AA7EAAND)作为工作基础 我遇到的问题是,我得去拿大约15000篇文章。在那之后,我需要遍历所有这些文件,根据文章id获取更多数据(与(继承的)媒体或价格等有直接和间接的关联)。大约50-100条记录也可以,但是如果

我正在做一个项目,我必须从数据库中收集大量数据。我使用Symfony2(symfony bf1281aebdc842a39ec0eb7438e1ea3fca9b9705)和Doctrine2(doctrine 3B3186EE98392802A44118CD421A353119AA7EAAND)作为工作基础

我遇到的问题是,我得去拿大约15000篇文章。在那之后,我需要遍历所有这些文件,根据文章id获取更多数据(与(继承的)媒体或价格等有直接和间接的关联)。大约50-100条记录也可以,但是如果我想使用更多的记录,那么从数据库中获取所有信息需要大量的ram

有没有一种方法可以在不耗尽所有剩余ram的情况下遍历数据?有没有办法告诉条令停止使用参考文献


提前感谢您的帮助

如果没有更多关于你想做什么的细节,很难回答

原则通常不适合于您可能描述的主要数据处理。我有几个项目依赖于仅仅使用DBAL来运行原始SQL来处理复杂的报表之类的事情

也就是说,如果您实际上不需要一次加载所有15k记录,那么不要立即加载它们!抓取50个,处理它们,释放内存,然后重复。这种方法可以在运行时保持总计,因此可以获得整个集合的一些聚合统计信息


这就是说,如果您需要聚合的东西,您可能正在构建某种“报告”,您最好使用纯SQL,甚至一些存储过程,不要让ORM参与进来。

您可以考虑在原则中使用迭代(逐步)水合作用:

$em = $this->getDoctrine()->getEntityManager();
$q  = $em->createQuery("<DQL to select the objects I want>");
$iterableResult = $q->iterate();
while (($row = $iterableResult->next()) !== false) {
    // do stuff with the data in the row, $row[0] is always the object
    $em->detach($row[0]); // detach from Doctrine, so that it can be GC'd immediately
}
$em=$this->getDoctrine()->getEntityManager();
$q=$em->createQuery(“”);
$iterableResult=$q->iterate();
while(($row=$iterableResult->next())!==false){
//处理行中的数据,$row[0]始终是对象
$em->detach($row[0]);//从条令中分离,以便可以立即对其进行GC
}

“质量对象处理”下的详细信息实际上还有另一种方法,但您不会喜欢它。您可以使用纯mysql:) 当我尝试使用getRepository(“..”->findAll()从数据库中获取450k对象时,我花了几个小时才关闭脚本:)。所以我使用了如下代码

    $c = $doctrine->getConnection();
    mysql_connect($c->getParams()['host'],$c->getParams()['user'],$c->getParams()['password']);//$link =
    mysql_select_db($c->getParams()['dbname']);
    $qid = mysql_query("SELECT id FROM TABLENAME");
    while($i = mysql_fetch_row($qid)) {
        $object = $doctrine->getRepository("...")->find($i[0]);
我在1.7秒后得到了第一个对象,这对我来说是绝对可以接受的。除了混乱的代码:(

在谷歌搜索了一段时间后,我找到了你们的问题。重写后,我得到了代码

    $iterableResult = $doctrine->getManager()->createQuery("SELECT c FROM ENTITY c")->iterate();

    while (($row = $iterableResult->next()) !== false) {
        $object = $row[0];
    }
上面的代码在2.4秒内提供了第一项,这与表中的doctrine2和450k项一样,速度非常快

我的观点是——doctrine2已经有了“现实生活”使用所需的几乎所有东西,但您仍然可以使用老式的丑陋代码简化您的生活:)

更新:不要忘记级联拆离所有加载的实体。在symfony2中,还需要通过运行代码来禁用SQL日志记录

    $doctrine->getConnection()->getConfiguration()->setSQLLogger(null);

使用以下命令保存另一行:

$iterableResult = $doctrine->getManager()->createQuery("SELECT c FROM ENTITY c")->iterate();

while ((list($obj) = $iterableResult->next()) !== false) {
    // do something with $obj
    $em->detach($obj);
}
根据学说:


请告诉我,在Symfony驱动的应用程序中,您一次需要15k记录吗?只有数据挖掘需要那么多数据,而Symfony不应该为其提供动力。仅供参考:链接已断开
$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
    $user = $row[0];
    $user->increaseCredit();
    $user->calculateNewBonuses();
    if (($i % $batchSize) === 0) {
        $em->flush(); // Executes all updates.
        $em->clear(); // Detaches all objects from Doctrine!
    }
    ++$i;
}
$em->flush();