Zend Framework, pdo_mysql и проблемы с ограничением памяти — почему?

У меня есть следующая установка:

  • Зенд Фреймворк 1.10.8
  • адаптер базы данных: pdo_mysql
  • ограничение памяти: 128MB
  • тип стола: мисам
  • размер таблицы: 4 МБ
  • количество записей: 22.000
  • количество столбцов: ок. 70

Я хочу выбрать все из таблицы, что не должно быть проблемой:

$table = new Application_Model_DbTable_Foo();
$everything = $table->fetchAll();

При этом я сталкиваюсь с проблемой «исчерпания памяти».

Я написал скрипт с использованием PDO_MYSQL без Zend Framework, и использование памяти было в порядке, и он работал нормально.

Так что я должен что-то пропустить здесь. Любая подсказка высоко ценится. :-)


person herrjeh42    schedule 05.11.2010    source источник
comment
Абстракция БД Zend Framework == НЕ ТАК_ ХОРОШО. Существует некоторая литература для перезаписи в v2.   -  person Andreas    schedule 05.11.2010


Ответы (4)


Одни только строки 22k могут содержать значительный объем данных, в зависимости от того, что делает ваш скрипт. Если увеличение лимита памяти не вариант, вы можете попробовать это. Захватывайте «куски» строк. Вы можете сделать это с помощью LIMIT. Установите размер страницы на то, что помещается в памяти, а затем обработайте это. Продолжайте увеличивать OFFSET, пока не обработаете все свои данные.

person Chris Henry    schedule 05.11.2010

Всем спасибо за внимание к моей проблеме. :-)

Для дальнейшего справки, если у кого-то еще есть эта проблема, я закончил так:

 $db = Zend_Db_Table_Abstract::getDefaultAdapter();
   $result = $db->query("SELECT * from footable");
   foreach ($result as $row) {            
           //print $row["field"]; 
  }
  unset($result);

... все еще рассматриваю возможность перехода к предложению «получить его порциями, используя LIMIT x, y».

person herrjeh42    schedule 06.11.2010

Я довольно много работал над компонентом Zend_Db, когда работал над проектом Zend Framework (до ZF 1.0).

Как говорит @netcoder, компонент Zend_Db_Table создает объекты для каждой извлеченной строки. Объекты занимают больше памяти, чем примитивные массивы, но они также дают вам возможность использовать объектно-ориентированное использование и save() и т. д.

Настоящая проблема в том, что вы делаете fetchAll() с большим набором данных. Даже если ваш лимит памяти может обрабатывать 22000 строк, завтра вам понадобится 44000 строк, а в следующем месяце 100000 строк.

Независимо от реализации Zend_Db или если вы используете PDO без фреймворка, вам нужно научиться управлять большими наборами данных, не загружая их полностью в память, потому что это неизбежно приведет к исчерпанию памяти. Это справедливо для любой библиотеки, фреймворка и даже любого языка.

Вы можете попробовать использовать LIMIT, как предлагает @Chris Henry, так что вы обязательно получите фиксированное количество строк, которое не слишком много.

Кроме того, вы можете извлекать данные построчно, чтобы в памяти была только одна строка. Класс Zend_Db_Table не предоставляет для этого средства; вам придется самостоятельно запускать SQL-запросы с помощью интерфейса Zend_Db_Adapter, а затем перебирать результаты с помощью fetch().

См. примеры на странице http://framework.zend.com/manual/en/zend.db.statement.html

person Bill Karwin    schedule 06.11.2010

Zend_Db использует множество абстракций, классов и т. д. Для каждой строки в вашем наборе результатов он создает объект (Zend_Db_Table_Row). Объект для каждой строки использует намного больше памяти, чем массив с парами ключ-значение.

person netcoder    schedule 05.11.2010