Разрешенный объем памяти, превышающий 256 МБ при простом запросе выбора mysql - PullRequest
3 голосов
/ 19 октября 2011

РЕДАКТИРОВАТЬ: Для любого, кто найдет это позже, CI будет использовать много памяти при таких обстоятельствах, так как он создаст объект для каждой строки (использование result_array () не кажется намного лучше), поэтому лучшая ставкаэто просто использовать встроенные в PHP функции mysql.Если вы используете MYSQLI, вы можете получить доступ к ссылке на соединение следующим образом:

$this->db->conn_id

Я пытаюсь запустить скрипт через командную строку (проверяя, что будет cronjob), что делает скриптне имеет значения, так как он терпит неудачу при первом выборе и больше не получает.

Я использую Codeigniter 2.0.3.

Моя таблица выглядит так:

CREATE TABLE IF NOT EXISTS `graphic_files` (
  `graphic_file_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `graphic_file_style_id` tinyint(2) unsigned NOT NULL,
  `graphic_file_fm_id` bigint(20) unsigned DEFAULT NULL,
  `graphic_file_config_line` varchar(255) NOT NULL,
  `graphic_file_config_line_hash` varchar(32) NOT NULL,
  `graphic_file_location` varchar(255) DEFAULT NULL,
  `graphic_file_pack_id` int(10) unsigned NOT NULL,
  `graphic_file_enabled` tinyint(1) NOT NULL,
  `graphic_file_alternative` tinyint(1) NOT NULL,
  `graphic_file_version` decimal(4,2) NOT NULL,
  `graphic_file_time_added` int(11) unsigned NOT NULL,
  `graphic_file_time_modified` int(11) unsigned NOT NULL,
  `graphic_file_size` int(11) unsigned NOT NULL,
  PRIMARY KEY (`graphic_file_id`),
  KEY `graphic_file_style_id` (`graphic_file_style_id`),
  KEY `graphic_file_fm_id` (`graphic_file_fm_id`),
  KEY `graphic_file_config_line_hash` (`graphic_file_config_line_hash`),
  KEY `graphic_file_pack_id` (`graphic_file_pack_id`),
  KEY `graphic_file_enabled` (`graphic_file_enabled`),
  KEY `graphic_file_version` (`graphic_file_version`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=240752 ;

Есть 240 000 строк.

Я пытаюсь выбрать около 120 000 из них с помощью этого запроса:

SELECT * FROM graphic_files WHERE graphic_file_enabled = 0 AND graphic_file_style_id = 5

Но я получаю ошибку допустимого размера памяти, например, так:

Допустимый объем памяти 268435456 байт исчерпан (попытался выделить 92 байта) в файле xxx / codeigniter_2.0.3 / database / drivers / mysqli / mysqli_result.php в строке 167

Я понимаюпростой ответ заключается в том, что мне не хватает памяти, но это кажется нелепым, если просто выполнить запрос на выборку, особенно с большим разрешенным объемом памяти 256 МБ.

Кто-нибудь может предложить причину этого?Может быть, это связано с codeigniter и тем, как он строит объект результатов?

Ответы [ 2 ]

9 голосов
/ 19 октября 2011

Хорошо, предполагая, что мы имеем дело с минимальным минимумом (просто используя объявленные размеры здесь), каждая строка данных составляет 624 байта.Это немного преуменьшает, потому что многие из этих полей переменной ширины занимают дополнительное место, чтобы заметить, насколько они велики.Учитывая, что все они будут преобразованы во внутренний стиль PHP, мы, вероятно, можем добавить немного больше (результаты возвращаются в виде массива, возможно, хеш зависит от настроек).Но в действительности мы, вероятно, будем иметь дело с почти 2 КБ на запись после того, как все это сказано и сделано.

Кроме того, мы имеем дело с 120 000 из них.120000 * 2048 = 245760000 байт = 234,4 МБ данных.У PHP есть накладные расходы, как и у codeigniter.Вместе этого более чем достаточно, чтобы вывести вас из предела памяти.

Если вы хотите получить более точную оценку объема используемой памяти, продолжайте и увеличьте предел использования памяти, затем после того, как вы сделаете выборзапрос, проверьте memory_get_usage () .

Что вы можете сделать, чтобы сократить использование памяти, либо уменьшить количество строк, выбираемых путем добавления дополнительных предложений where, выбрать только необходимые столбцывместо всех или используйте оператор LIMIT.Если вы идете по маршруту LIMIT, вы можете обрабатывать все записи и все столбцы, но порциями.Каждый оператор select может возвращать ограниченное количество строк, скажем, 100, но вы можете сделать каждый последующий вызов возобновить там, где остановился другой.Таким образом, вы никогда не будете иметь более 100 строк данных в памяти в данный момент времени.

5 голосов
/ 19 октября 2011

С большими данными вам нужно использовать mysql resource вместо функций CI

$result = $this->db->query($sql);
$resource = $result->result_id;
while($row = @mysql_fetch_assoc($resource)) {
    // do the magic
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...