简单的mysql选择查询允许的内存大小超过256mb

Joh*_*lor 3 php mysql codeigniter

编辑:对于在以后发现这种情况的任何人,CI会在这些情况下使用大量内存,因为它会为每一行创建一个对象(使用result_array()似乎没有好多了),所以最好的选择就是使用PHP内置的mysql函数.如果您正在使用MYSQLI,则可以访问连接链接,如下所示:

$this->db->conn_id
Run Code Online (Sandbox Code Playgroud)

我正在尝试通过命令行运行脚本(测试什么是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 ;
Run Code Online (Sandbox Code Playgroud)

有240,000行.

我试图用这个查询选择大约120,000个:

SELECT * FROM graphic_files WHERE graphic_file_enabled = 0 AND graphic_file_style_id = 5
Run Code Online (Sandbox Code Playgroud)

但我得到一个允许的内存大小错误,如下所示:

第167行的xxx/codeigniter_2.0.3/database/drivers/mysqli/mysqli_result.php中允许的内存大小为268435456字节(试图分配92字节)

我意识到简单的答案是我内存不足,但这对于简单地执行选择查询来说似乎很荒谬,特别是对于256mb的高允许内存大小.

任何人都可以提出这个理由吗?可能与codeigniter及其构建结果对象的方式有关吗?

Mr.*_*ama 9

好吧,假设我们正在处理最低限度(仅使用声明的大小),每行数据为624字节.这有点轻描淡写,因为许多可变宽度字段需要额外的空间来记录它们实际有多大.鉴于所有这些都将转换为内部PHP样式,我们可能会在那里进行更多处理(结果作为数组返回,可能是根据设置的哈希).但实际上,在完成所有操作后,我们可能会处理总计近2kb的记录.

此外,我们正在处理其中的120,000个.120000*2048 = 245760000字节= 234.4 MB的数据.PHP有它的开销,codeigniter也是如此.总之,这足以让你超越内存限制.

如果您想更好地估计正在使用的内存量,请继续并调高内存使用量限制,然后在执行select查询后,检查memory_get_usage().

您可以采取哪些措施来减少内存使用量,或者通过添加额外的where子句来减少所选行的数量,只选择必要的列而不是所有列,或者使用LIMIT语句.如果你进入LIMIT路线,你可以处理所有记录和所有列,但是以块为单位.每个select语句都可以返回有限数量的行,比如100,但是你可以让每个后续的调用恢复到另一个停止的地方.这样,在给定时间内,内存中永远不会有超过100行数据.


Pet*_*ter 5

对于大数据,您需要使用mysql resource而不是CI功能

$result = $this->db->query($sql);
$resource = $result->result_id;
while($row = @mysql_fetch_assoc($resource)) {
    // do the magic
}
Run Code Online (Sandbox Code Playgroud)