基本 Doctrine MongoDB 抛出内存不足异常

问题描述 投票:0回答:2

我的数据库中有大约 60k 文档,但我无法查询它们。 我能够成功检索它们的唯一方法是使用水合物(假)选项。

我都尝试过:

$dm = $this->get('doctrine_mongodb')->getManager();
    $qb = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
        ->eagerCursor(true);
    $query = $qb->getQuery();
    $results = $query->execute();

$dm = $this->get('doctrine_mongodb')->getManager();
    $qb = $dm->createQueryBuilder('BConwayWebsiteBundle:Business');
    $query = $qb->getQuery();
    $results = $query->execute();

如果我转储 $results->isInitialized() 它是错误的。 我相信这是因为我当时还没有使用它。 我尝试执行的任何访问都会导致内存问题。 甚至像 $results->count() 这样基本的东西。

[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"find":true,"query":[],"fields":[],"db":"ClosedForTheHoliday","collection":"businesses"} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"limit":true,"limitNum":null,"query":[],"fields":[]} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"skip":true,"skipNum":null,"query":[],"fields":[]} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"sort":true,"sortFields":[],"query":[],"fields":[]} [] []
[2013-10-01 23:54:56] emergency.EMERGENCY: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) {"type":1,"file":"/media/sf_sites/cfth_com/vendor/doctrine/mongodb/lib/Doctrine/MongoDB/Cursor.php","line":237} []

更新:如果我将结果限制为 2000,它就有效。 此外,如果我只选择查询后要使用的两个字段,我可以将其限制为 15000 并获得成功。 当我将其限制为 2000 时,开发调试栏显示查询使用了 120MB 内存。 我需要能够迭代所有结果,并且它无法分页。 看来没有 100MB 以上的查询就应该可以实现...

php mongodb doctrine
2个回答
0
投票

我只需要来自两个字段的不同数据,所以这就是我最终所做的:

$dm = $this->get('doctrine_mongodb')->getManager();

// Get organization name from all businesses (distinct)
$organizations = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
    ->distinct('organization')
    ->getQuery()
    ->toArray();

// Get business name from all businesses (distinct)
$names = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
    ->field('organization')->equals('')
    ->field('organization')->equals(null)
    ->distinct('name')
    ->getQuery()
    ->toArray();

// Create new array from results of both queries
$businesses = array_merge($organizations, $names);

// Filter out any null or empty values
$businesses = array_filter($businesses, function($item) {
    return (!is_null($item) && strlen($item) > 0);
});

// Filter out any duplicates
array_unique($businesses);

// Sort array case-insensitive
sort($businesses, SORT_STRING | SORT_FLAG_CASE);

0
投票

由于 Doctrine MongoDB ODM 是一个持久性管理器(与关系数据库的 Doctrine ORM 2.x 类似),对水合对象的引用存储在内部,并且不会像迭代非水合数组那样容易被 PHP 的垃圾回收恢复结果很快就超出了范围。

对于 Doctrine 中的任何批处理操作,您需要定期

clear()
所有托管对象的对象管理器,或手动
detach()
单个对象。在您的情况下,定期
clear()
可能是最简单的,因为您可以在结果的每 X 次迭代中执行此操作。您可以在这篇博文中找到一些代码示例以及对此解决方案的讨论。尽管它是从 ORM 及其 EntityManager 类的角度编写的,但 ODM 的 DocumentManager 实现了 Doctrine Common 库中相同的 ObjectManager 接口,您可以在其中找到
detach()
clear()
方法。

© www.soinside.com 2019 - 2024. All rights reserved.