10

假设我有

$db is an instance of Zend_Db_Adapter_Abstract and
$sql = 'SELECT blah blah FROM table' will return a huge number of records.

有两个代码片段来处理返回的数据,如下所示。

// Code fragment 1 (let's call it C1).
$results = $db->fetchAll($sql);
foreach ($results as $row) {
    // Process $row
}

// Code fragment 2 (let's call it C2).
$stmt = $db->query($sql);
while ($row = $stmt->fetch()) {
    // Process $row
}

我的理解是 C1 会将所有返回的数据加载到 $results 中。因此,大量数据被加载到 PHP 内存中。以下是我的问题。

  1. C2 是将所有数据加载到 PHP 内存还是像准备/执行一样一一处理?
  2. 假设没有其他选择,C1 或 C2 是更好的选择吗?

谢谢!

4

2 回答 2

17

你的预感是正确的。至少如果您使用 PDO 驱动程序,->fetch() 会读取未缓冲的结果,而 ->fetchAll() 会返回大数组中的所有数据。

请注意,如果您使用 ->fetch(),则必须小心在循环中尝试执行的操作。当您仍然有一个无缓冲的结果集时,您不能在同一连接上运行其他查询。

因此,如果您的计划是在循环中更新这些相同的行,您将需要找到一种方法来延迟执行更新(通过排队然后以某种方式),直到您退出循环。

于 2012-05-05T21:16:32.900 回答
10

要从结果集中检索一行,请使用语句对象的 fetch() 方法。参考

$sql = 'SELECT blah blah FROM table';
$stmt = $db->query($sql);
while ($row = $stmt->fetch()) {
    // Process $row
}

在上面的示例中,$stmt = $db->query($sql);检索了resultset内存中的 并fetch用于从 中获取循环中的当前行resultset,这会将光标移动到下一行,直到到达 中的最后一行resultset

要在一个步骤中检索结果集的所有行,请使用 fetchAll() 方法。这相当于在循环中调用 fetch() 方法并返回数组中的所有行。

$sql = 'SELECT blah blah FROM table';
$stmt = $db->query($sql);
$rows = $stmt->fetchAll();
echo $rows[0]['col1']; // The first field/column from the first row

或者,您可以使用

....
$table = new Mytable();
// Find a single row Returns a Rowset
$rows = $table->find(1234);

// Find multiple rows Also returns a Rowset
$rows = $table->find(array(1234, 5678));

参考: Zend_Db_Table。.

更多信息: 获取一行。.

我认为fetchAll()更快,因为它一步检索所有数据并返回一个数组但消耗更多内存但fetch()消耗更少内存但逐个检索数据。

获取操作的 API 已被取代,以允许 Zend_Db_Table_Select 对象修改查询。但是,不推荐使用的 fetchRow() 和 fetchAll() 方法将继续工作而无需修改。

更多参考: 这里。

于 2012-05-05T21:57:21.023 回答