Большой набор результатов SQL занимает слишком много памяти - CodeIgniter - PullRequest
1 голос
/ 11 января 2012

Я выдаю SQL-запрос с использованием CodeIgniter, который может возвращать более 80000 строк в качестве результатов. Каждая строка имеет три столбца, все из которых являются целыми числами, и я получаю ошибку PHP: Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан

Кажется, я пытаюсь использовать более 128 МБ для получения результатов с сервера MySQL. Я использую $ query-> result_array () для получения результатов. Очевидно, что в результатах, которые я получаю, возникают серьезные накладные расходы. Скажем, я получаю 100 000 строк с 3 целыми числами. Таким образом, 100 000 * ((3 * 4 + 10) = 2,1 МБ. (10 - это количество байтов, используемых для идентификатора столбца и т. Д.).

Я что-то не так делаю?

---------------------- решаемые -----------------------

Решено путем изменения кода CodeIgniter: ссылка .

Выполнение теперь выполняется быстрее, и сценарий занимает всего ~ 3 МБ памяти вместо 128 МБ.

Ответы [ 5 ]

2 голосов
/ 11 января 2012

Я не уверен, как именно CI возвращает результаты, но вам определенно не нужен весь этот набор данных в одном массиве. Почему бы не перебрать все строки по мере необходимости?

<?php

$result = $this->db->query('SELECT ...');
while($row = $result->next_row())
{
  // do something with that single row
}
1 голос
/ 11 января 2012

Если вы отображаете результаты на странице, вам, скорее всего, придется использовать нумерацию страниц. Если вы выполняете действия с данными, вам нужно будет делать это по частям, используя LIMITS и OFFSETS. В противном случае вам потребуется увеличить лимит памяти, который не рекомендуется превышать 128 МБ.

1 голос
/ 11 января 2012

За исключением того, что вам действительно нужно получить все записи - например, для целей экспорта или пакетной обработки - я настоятельно рекомендую всегда запрашивать куски .

В операторе SELECT MySQL есть эта опция :

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

Например

Limit 10, 200

обеспечивает 200 записей, начинающихся с записи 10 .

0 голосов
/ 03 апреля 2016

Я столкнулся с той же проблемой с CI.К сожалению, изменение базы данных БД не было для меня вариантом.Поэтому мое решение состояло в том, чтобы просто использовать mysqli_ функции в модели и перебирать каждую запись по отдельности:

$result = mysqli_query($sql);
while ($row = mysqli_fetch_assoc($result)){
    // process batch
}

И работать с записями таким образом, мне не нужно было делать ни паутину, нихранить всю информацию на 1 массив.Это также работает с функциями mysql_ (в зависимости от используемого драйвера БД).Недостатки здесь:

  • Вы не используете CI DB engine, поэтому, если вы решите использовать другой драйвер, вам придется вручную обновить эти запросы.
  • Не будет работатьс несколькими БД, если только вы каким-то образом не сохраните идентификатор БД.

Могут быть и другие недостатки, но для меня это работает и не требует большого количества данных.

0 голосов
/ 11 января 2012

Несмотря на то, что на вопрос дан ответ, 3МБ все еще много.Вам действительно нужно хранить все это в памяти?Обычная площадь PHP занимает около 1 МБ или меньше, учитывая, что она была запрограммирована с учетом памяти.Тот факт, что вы можете даже преодолеть 8 МБ, очень беспокоит, и в реальной производственной среде с тысячами обращений к страницам ваш сервер будет зависать и работать.Я настоятельно рекомендую вам пересмотреть свой код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...