索引查询结果
当你在调用 yii\db\Query::all() 方法时,它将返回一个以连续的整型数值为索引的数组。 而有时候你可能希望使用一个特定的字段或者表达式的值来作为索引结果集数组。那么你可以在调用 yii\db\Query::all() 之前使用 yii\db\Query::indexBy() 方法来达到这个目的。 例如,
// 返回 [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 => [...], ...]$query = (new \yii\db\Query())
->from('user')
->limit(10)
->indexBy('id')
->all();
如需使用表达式的值做为索引,那么只需要传递一个匿名函数给 yii\db\Query::indexBy() 方法即可:
$query = (new \yii\db\Query())
->from('user')
->indexBy(function ($row) {
return $row['id'] . $row['username'];
})->all();
该匿名函数将带有一个包含了当前行的数据的 $row
参数,并且返回用作当前行索引的 标量值(译者注:就是简单的数值或者字符串,而不是其他复杂结构,例如数组)。
批处理查询
当需要处理大数据的时候,像 yii\db\Query::all() 这样的方法就不太合适了, 因为它们会把所有数据都读取到内存上。为了保持较低的内存需求, Yii 提供了一个 所谓的批处理查询的支持。批处理查询会利用数据游标将数据以批为单位取出来。
批处理查询的用法如下:
use yii\db\Query;
$query = (new Query())
->from('user')
->orderBy('id');
foreach ($query->batch() as $users) {
// $users 是一个包含100条或小于100条用户表数据的数组
}
// or if you want to iterate the row one by oneforeach ($query->each() as $user) {
// $user 指代的是用户表当中的其中一行数据
}
yii\db\Query::batch() 和 yii\db\Query::each() 方法将会返回一个实现了Iterator
接口 yii\db\BatchQueryResult 的对象,可以用在foreach
结构当中使用。在第一次迭代取数据的时候, 数据库会执行一次 SQL 查询,然后在剩下的迭代中,将直接从结果集中批量获取数据。默认情况下, 一批的大小为 100,也就意味着一批获取的数据是 100 行。你可以通过给 batch()
或者 each()
方法的第一个参数传值来改变每批行数的大小。
相对于 yii\db\Query::all() 方法,批处理查询每次只读取 100 行的数据到内存。 如果你在处理完这些数据后及时丢弃这些数据,那么批处理查询可以很好的帮助降低内存的占用率。
如果你通过 yii\db\Query::indexBy() 方法为查询结果指定了索引字段,那么批处理查询将仍然保持相对应的索引方案,例如,
$query = (new \yii\db\Query())
->from('user')
->indexBy('username');
foreach ($query->batch() as $users) {
// $users 的 “username” 字段将会成为索引
}
foreach ($query->each() as $username => $user) {
}