$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 on 第167行
我意识到简单的答案是我内存不足,但这对于简单地执行选择查询来说似乎很荒谬,特别是对于256mb的高允许内存大小。
有人可以提出理由吗?可能与codeigniter及其构建结果对象的方式有关吗?
答案 0 :(得分:9)
好的,假设我们正在处理最低限度(仅使用声明的大小),每行数据为624字节。这有点轻描淡写,因为许多可变宽度字段需要额外的空间来记录它们实际有多大。鉴于所有这些都将转换为内部PHP样式,我们可能会在那里进行更多处理(结果作为数组返回,可能是根据设置的哈希)。但实际上,在完成所有操作后,我们可能会处理总计近2kb的记录。
另外,我们正在处理其中的120,000个。 120000 * 2048 = 245760000字节= 234.4 MB的数据。 PHP有它的开销,codeigniter也是如此。总之,这足以让你超越内存限制。
如果您想更好地估计正在使用的内存量,请继续并提高内存使用量限制,然后在执行选择查询后,请检查memory_get_usage()。
您可以采取哪些措施来减少内存使用量,或者通过添加额外的where子句来减少所选行的数量,只选择必要的列而不是所有列,或者使用LIMIT语句。如果你进入LIMIT路线,你可以处理所有记录和所有列,但是以块为单位。每个select语句都可以返回有限数量的行,比如100,但是你可以让每个后续的调用恢复到另一个停止的地方。这样,在给定时间内,内存中永远不会有超过100行数据。
答案 1 :(得分:5)
对于大数据,您需要使用mysql resource
而不是CI功能
$result = $this->db->query($sql);
$resource = $result->result_id;
while($row = @mysql_fetch_assoc($resource)) {
// do the magic
}