文档中描述的正常result()
方法似乎可以立即加载所有记录。我的应用程序需要加载大约 30,000 行,一次一个,将它们提交给第三方搜索索引 API。显然,一次将所有内容加载到内存中效果不佳(由于内存过多而导致错误)。
所以我的问题是,我怎样才能达到传统 MySQLi API 方法的效果,在循环中一次加载一行?
文档中描述的正常result()
方法似乎可以立即加载所有记录。我的应用程序需要加载大约 30,000 行,一次一个,将它们提交给第三方搜索索引 API。显然,一次将所有内容加载到内存中效果不佳(由于内存过多而导致错误)。
所以我的问题是,我怎样才能达到传统 MySQLi API 方法的效果,在循环中一次加载一行?
这是您可以做的事情。
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() 方法时他们会这样做。
对于那些想要在大型结果集上节省内存的人:
从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;
}
您可以选择传递“对象”(默认)或“数组”以指定返回值的类型:
$query->unbuffered_row(); // object
$query->unbuffered_row('object'); // object
$query->unbuffered_row('array'); // associative array
官方文档:https ://www.codeigniter.com/userguide3/database/results.html#id2
好吧,事情是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
goresult()
和foreach()
每个页面加载多个 api 更高的数字。
好吧,有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 次调用,或者选择所有结果并一次获取一个,或者您获取所有结果并遍历数组。我现在看不到任何出路。