Задать вопрос
@bighoc
php/javascript developer

Почему yii сьедает так много памяти при больших запросах?

Я делаю запросы через Yii::app()->db->createCommand которые в итоге получаються достаточно большими (100-150 тысяч симовлов). Возвращают эти запросы не большие данные. Проблема состоит в том что Yii где хранит историю запросов и когда в форыче я делаю 100 ( а мне надо их сделать 20 000 :) ) таких запросов у меня фатал
Fatal error: Allowed memory size
.

Запрос который я делаю
$ids = Yii::app()->db->createCommand()
                    ->select('user_id')
                    ->from('user_community')
                    ->where("community_id = :community_id AND user_id IN({$subjectsIn})", [
                        ':community_id' => $communityId
                    ])
                    ->queryColumn();

subjectsIn
- это и есть строка из 120 тысяч симоволов.
Собираюсь использовать TEMP TABLE, но хотелось бы конечно обойти это ограничение Yii

Собственно как это обойти ?
  • Вопрос задан
  • 476 просмотров
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 6
Покажите код, это намного увеличит вероятность нахождения правильного решения.

Проблемы может быть две:
1) При каждой итерации создаются новые объекты и не очищаются по завершению
2) Объекты очищаются, но из-за большого размера и малого количества не обрабатываются сборщиком мусора

Для решения первой проблемы достаточно делать unset для ненужных объектов

Для решения второй - делать gc_collect_cycles. Поскольку эта операция трудоемкая, можно делать ее раз в 10/100/1000 циклов, подберите сами.
На тему сборки мусора: php.net/manual/ru/features.gc.performance-consider...
Если вкратце, сборщик мусора вызывается при достижении кол-ва неиспользуемых объектов 10000. Поэтому, если объекты большие и 10000 штук не влезает в память, будет переполнение.
Ответ написан
Demetriy
@Demetriy
веб и мобильная разработка
Batch, наверно это должно помочь, почитайте.
Ответ написан
<?php ini_set("memory_limit", "1000M"); ?>
Ответ написан
Комментировать
Перепишите конкретно этот блок с запросами на PDO или mysqli и всё станет отлично
Ответ написан
Комментировать
Отключите в cdbconnection дебаг, профайлинг и всё такое.
Ответ написан
Комментировать
@Evgeny_Shestakov
как получаете этот $subjectsIn - массив user_id? может лучше не хранить эту переменную в памяти вообще, а делать запрос вида SELECT * FROM table1 WHERE id IN (SELECT id FROM table2); т.е. место ... AND user_id IN({$subjectsIn}) ... переписать на ... AND user_id IN (SELECT user_id FROM `user_community` WHERE condition) ...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы