Dutchakdev

Code, hacks and Rock and Roll.

Пакетная обработка данных для AR YII

| Comments

Хотел немного поиграться и посмотреть что выйдет. В yii2 есть такая крутая мега фича как batch и each. Юзаются они так:

1
2
3
4
5
6
7
8
9
10
11
12
13
use yii\db\Query;

$query = (new Query)
    ->from('tbl_user')
    ->orderBy('id');

foreach ($query->each() as $user) {
    // $user — одна строка из tbl_user
}

foreach ($query->batch(10) as $users) {
    // $users — массив из 10 строк
}

Конечно так красиво сделать не выйдет, да и вообще, не выйдет повторить всю суть, без значительных изминений в AR (новый, для версии 2 команда yii писала 2 года) но поигратся было интересно.

Посмотреть что получилось можно тут: https://github.com/dutchakdev/yii-batch Репозиторий еще не дооформил, нужно написать пару тестов и пример использования в демо проекте.

Сам компонент (хоть он и больше хелпер-итератор) находится тут https://github.com/dutchakdev/yii-batch/blob/master/protected/components/Batch.php

Вышло у мен так:

Batch:

1
2
3
4
// Вытягиваем по 10 штук из базы, когда мы их все проходим, догружаем еще 10
foreach((new \Batch(10, \user\models\User::model()))->findAll($criteria) as $item){
  // В $item находится 10 обьектов
}

Each:

1
2
3
4
// Вытягиваем по 10 штук из базы, когда мы их все проходим, догружаем еще 10 отдельным запросом
foreach((new \Batch(10, \user\models\User::model(), true))->findAll($criteria) as $item){
  // В $item находится 1 обьект
}

Штука работает довольно медленно за счет того что делает несколько запросов к базе, но память экономит значительно. Сравнивая с обычным findAll из AR, который 3400 моих записей из реального проекта сожрал 94.5 mb в то время когда batch держал уровен в районе 18.5-19.5 mb (учитывая что batchSize, размер пакета, был равен 100).

Если немного допилить AR для этих дел можно добится в уменьшения в раза два, но я пока не стал заморачиватся так как интерес был не в том.

Заключение Получилось не плохо, хоть и мало применимо. Для данных большого размера априори плохо юзать AR, в yii2 ситуация улучшилась в разы (переключатель массив/обьект, перепиленый AR в котором гараздо удобней управлять данными). Но иногда бывают ситуации когда можно себе позволить использовать обьект AR для выборки и в несколько запросов, к примеру отчетов или выгрузки плоских таблиц. Во всяком случае это мой маленький эксперимент которым я хочу поделится.

Так же скоро планирую написать нечто похожее на генераторах, есть несколько соображений.

Comments