Browse Source

Adjusted text [skip ci]

tags/2.0.12
Alexander Makarov 7 years ago committed by GitHub
parent
commit
974a1eeb48
  1. 24
      docs/guide/db-query-builder.md

24
docs/guide/db-query-builder.md

@ -652,17 +652,12 @@ value which will be used as the index value for the current row.
### Batch Query <span id="batch-query"></span>
When working with large amounts of data, methods such as [[yii\db\Query::all()]] are not suitable because they require loading all data into the memory. To keep the memory requirement low, an [`Unbuffered Query`](http://php.net/manual/en/mysqlinfo.concepts.buffering.php) is needed. In this mode, the MySQL Server will hold the result data set cursor, waiting the client to get data for every iteration.
> Warning: Unless whole data set has been retrieved, no other query could be done through the same connection. The table may remains locked by MySQL and cannot be written to by other queries.
Yii provides the so-called batch query support. A batch query makes use of the data cursor and fetches data in batches, but the `$db` parameter is not the one that have `PDO::MYSQL_ATTR_USE_BUFFERED_QUERY`
disabled before `version 2.0.11.2` by default, [and maybe won't ever](https://github.com/yiisoft/yii2/issues/8420) (still under discussion for now), because there is [`No Silver Bullet`](https://github.com/yiisoft/yii2/issues/8420#issuecomment-295679232) for this.
Before PHP 5.6, the memory usage of buffered query in drivers does not count towards PHP's memory limit, but it takes the memory actually, it may eat all your servers' memory and get your PHP-FPM
process killed. It is Suggested that you create a new connection to MySQL Server , which the `PDO::MYSQL_ATTR_USE_BUFFERED_QUERY` is set to `false` at your need manually.
Assume that you have a set a connection to `$unbuffered_db` which the `BUFFERED_QUERY` is off. Batch query can be used like the following at a low memory cost of PHP:
When working with large amounts of data, methods such as [[yii\db\Query::all()]] are not suitable because they require loading all data into the memory. To solve the issue Yii provides batch query support. Server holds the result data set cursor, waiting the client to get data for every iteration.
> Warning: In order to use it and keep the memory requirement low in case of using MySQL, an [`Unbuffered Query`](http://php.net/manual/en/mysqlinfo.concepts.buffering.php) should be used by setting connection `PDO::MYSQL_ATTR_USE_BUFFERED_QUERY` to `false`. Unless whole data set has been retrieved, no other query could be done through the same connection. The table may remain locked by MySQL and cannot be written to by other queries. Thus, new connection should be created for this purpose.
>
> Assume that you have set up a connection to `$unbuffered_db` with `BUFFERED_QUERY` set to `false`. Batch query can be used like the following at a low memory cost of PHP:
>
```php
use yii\db\Query;
@ -670,24 +665,25 @@ $query = (new Query())
->from('user')
->orderBy('id');
foreach ($query->batch(100,$unbuffered_db) as $users) {
foreach ($query->batch(100, $unbuffered_db) as $users) {
// $users is an array of 100 or fewer rows from the user table
}
// or if you want to iterate the row one by one
foreach ($query->each(100,$unbuffered_db) as $user) {
foreach ($query->each(100, $unbuffered_db) as $user) {
// $user represents one row of data from the user table
}
```
The method [[yii\db\Query::batch()]] and [[yii\db\Query::each()]] return an [[yii\db\BatchQueryResult]] object which implements the `Iterator` interface and thus can be used in the `foreach` construct.
During the first iteration, a SQL query is made to the database. Data are then fetched in batches
in the remaining iterations. By default, the batch size is 100, meaning 100 rows of data are being fetched in each batch.
You can change the batch size by passing the first parameter to the `batch()` or `each()` method.
Compared to the [[yii\db\Query::all()]], the batch query only loads 100 rows of data at a time into the memory in `UNBUFFERED_QUERY` mode.
Compared to the [[yii\db\Query::all()]], the batch query only loads 100 rows of data at a time into the memory.
If `BUFFERED_QUERY` not configured properly, the `batch()` or `each()` method still hold all the data set in PDO's memory, this is be done in the driver level.
> Warning: If `BUFFERED_QUERY` is not configured properly, the `batch()` or `each()` method still hold all the data set in PDO's memory, this is done at the driver level.
If you specify the query result to be indexed by some column via [[yii\db\Query::indexBy()]], the batch query will still keep the proper index.

Loading…
Cancel
Save