文档中描述的正常result()
方法似乎会立即加载所有记录。我的应用程序需要加载大约30,000行,并且一次一个,将它们提交给第三方搜索索引API。显然,将所有内容一次加载到内存中并不能很好地工作(由于内存过多而导致错误)。
所以我的问题是,如何实现常规MySQLi API方法的效果,在循环中一次加载一行?
答案 0 :(得分:9)
这是你可以做的事情。
while ($row = $result->_fetch_object()) {
$data = array(
'id' => $row->id
'some_value' => $row->some_field_name
);
// send row data to whatever api
$this->send_data_to_api($data);
}
这将在当时获得一行。检查CodeIgniter源代码,您将看到执行result()方法时它们将执行此操作。
答案 1 :(得分:3)
对于那些想要在大型结果集上保存内存的人:
自 CodeIgniter 3.0.0 以来,
有一个unbuffered_row
函数,
上述所有方法都会将整个结果加载到内存中(预取)。使用unbuffered_row()处理大型结果集。
此方法返回单个结果行,而不像row()那样在内存中预取整个结果。如果您的查询有多行,则返回当前行并向前移动内部数据指针。
$query = $this->db->query("YOUR QUERY");
while ($row = $query->unbuffered_row())
{
echo $row->title;
echo $row->name;
echo $row->body;
}
您可以选择传递'object'(默认值)或'array'以指定返回值的类型:
$query->unbuffered_row(); // object
$query->unbuffered_row('object'); // object
$query->unbuffered_row('array'); // associative array
正式文件:https://www.codeigniter.com/userguide3/database/results.html#id2
答案 2 :(得分:0)
嗯,有 row() 方法,它只返回一行作为对象,或者 row_array()方法,它执行相同的操作但是返回一个数组(当然)。
所以你可以做类似
的事情$sql = "SELECT * FROM yourtable";
$resultSet = $this->db->query($sql);
$total = $resultSet->num_rows();
for($i=0;$i<$total;$i++) {
$row = $resultSet->row_array($i);
}
从整个结果集中获取每一行的循环。
这与我相信的$this->db->query($sql)->result()
方法调用的获取和循环大致相同。
如果你想要一次一行,你要么进行30.000次调用,要么你选择所有结果并一次一个地获取它们,或者你获取所有结果并遍历数组。我现在看不出任何出路。
答案 3 :(得分:0)
嗯,问题是result()
放弃了查询的整个回复。 row()
只是获取第一个案例并转储其余案例。但是,查询仍然可以获取您使用的函数的30 000行。
符合您事业的一种设计是:
$offset = (int)@$_GET['offset'];
$query = $this-db->query("SELECT * FROM table LIMIT ?, 1", array($offset));
$row = $query->row();
if ($row) {
/* Run api with values */
redirect(current_url().'?offset'.($offset + 1));
}
这将占用一行,将其发送到api,更新页面并使用下一行。它还可以防止页面超时。但是,很可能需要一段时间才能有30 000条记录并刷新,因此您可能需要将LIMIT ?, 1
调整为高于1
的数字,然后转到result()
和foreach()
多个api per pageload。