Doctrine - утечка памяти при выполнении namedQuery? - PullRequest
2 голосов
/ 09 марта 2019

Я использую Symfony 3.4 вместе с доктриной для моего проекта. В одной из команд, где я генерирую ранжирование для пользователей, я столкнулся с потенциальной утечкой памяти при использовании namedQuery (хотя могу ошибаться).

В каждой итерации цикла (более 2000 записей) я запускаю метод EntityManager->clear() вместе с gc_collect_cycles() (просто для обеспечения правильной сборки мусора). Хотя использование памяти сразу после 10000 итераций возрастает до 500 МБ, что действительно странно, так как обычно работает в других командах, использующих queryBuilder для формирования запросов.

Я убедился, что никакой другой код не отвечает за эту проблему с памятью, и извлек выполнение для получения результатов и выполнения именованного запроса.

Я также пытался отключить sql logger в конфигурации менеджера сущностей, но это не помогло. У кого-нибудь есть идеи, что может быть не так?

NamedQuery

SELECT SUM(a.points) FROM __CLASS__ a WHERE a.user = :user GROUP BY a.user

Проблемная часть кода (до ~ 500 МБ):

$query = $this->createNamedQuery('count_points');
$query->setParameter('user', $user->getId());
$query->setCacheable(false);

return $query->getSingleScalarResult();

Решение без утечки памяти (до ~ 60-70 МБ):

$query = $this->createNamedQuery('count_points');
$query->setParameter('user', $user->getId());
$query->setCacheable(false);

// bypass named query execution through doctrine for memory saving
$sql = $query->getSQL();
$conn = $this->getEntityManager()->getConnection();
$stmt = $conn->prepare($sql);
$stmt->execute([$user->getId()]);
unset($query);

return (int)$stmt->fetch(\PDO::FETCH_COLUMN);

1 Ответ

0 голосов
/ 20 марта 2019

У меня проблемы с памятью в связи с $query->getSingleScalarResult().

Если я обменяю return $query->getSingleScalarResult(); на

$r = return $query->getResult();
return $r[0]['mysum'];

Утечка исчезла. Вы должны немного изменить запрос и дать результату имя:

SELECT SUM(a.points) AS mysum FROM __CLASS__ a WHERE a.user = :user GROUP BY a.user
...