Symfony2: запрос Doctrine выделяет смехотворный объем памяти

#php #performance #symfony #doctrine-orm

#php #Производительность #symfony #doctrine-orm

Вопрос:

Я выполняю фильтрацию с помощью Doctrine QueryBuilder, который возвращает около 80 тыс. записей. Я выбираю только три поля (два идентификатора для двух соединенных объектов и одну строку, которая представляет собой строку длиной = 255 (никогда не бывает такой длинной, обычно около 30-40 символов). Я использую getArrayResult() .

 $filterResult = $this->getDoctrine()->getRepository('Bundle:Entity')
    ->createQueryBuilder('alias')
    -> // selects, joins, wheres
    ->getArrayResult();
  

Я понимаю, что выполнение может занять некоторое время из-за некоторых объединений и т. Д., Но я заметил, что после выполнения и сохранения результата в переменной (массив, 80 тыс. Записей, каждая из которых представляет собой массив из 3: id / id / name) потребляемая память примерно на 70 МБ больше.

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

Это странно, потому что, когда в другом месте я сохраняю только один столбец в простой массив с

 $idsOnly = array_column($filterResult, "id"); // 80k of IDs
  

Это занимает около 4 МБ.

Теперь, что я пробовал (в prod среде, конечно):
logging и profiling для doctrine.dbal значения false в config.yml (ничего в config_prod.yml , поэтому я предполагаю, что оно остается включенным prod )
$this->getDoctrine()->getConnection()->getConfiguration()->setSQLLogger(null); в действии фильтрации контроллера вверху
$filterResult = null; , затем gc_collect_cycles()
$em->clear() и gc_collect_cycles() практически везде, где я мог

И ничего не изменилось. С моей точки зрения, либо многомерные массивы занимают так много места, либо Doctrine оставляет некоторый мусор при извлечении результатов из БД. Что еще я должен попробовать, кроме NativeSQL?

Комментарии:

1. Просто для объявления массива, где каждая запись представляет собой массив из трех целых чисел, потребуется около 32 МБ. т.е. eval.in/654307 . Каждая переменная в PHP занимает около 144 байт;-/ Это PHP и не имеет ничего общего с Doctrine.

2. Вы правы… Но когда я перешел с QueryBuilder на raw SQL, теперь он использует половину общей памяти, что говорит о том, что Doctrine есть что мне объяснить! 🙂

3. Ну, если это всего лишь дополнительные 35 МБ, это, вероятно, понятно, doctrine добавляет дополнительный уровень, как вы знаете, выше mysql, и должен преобразовать конструктор запросов synthax в фактический запрос и (я думаю) получить фактические результаты…