索引查詢結果
當你在調用 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) {
}