оптимизация количества запросов ActiveRecord

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 09:41

Код: Выделить всё

$model = Model::findOne(3);
$model->time = time();
$model->save();
получается два запроса SELECT и UPDATE
моя задача например обновить только одно поле в записи и не гонять по сети кучу данных.
как это проще и правильнее сделать при помощи ActiveRecord
так будет правильно и оптимально ?
Model::updateAll(['id' => 3], 'time' => time());

Аватара пользователя
ElisDN
Сообщения: 5014
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: оптимизация количества запросов ActiveRecord

Сообщение ElisDN » 2018.05.30, 10:26

an.viktory@gmail.com писал(а):
2018.05.30, 09:41
моя задача например обновить только одно поле в записи и не гонять по сети кучу данных.
Кучу данных?

Аватара пользователя
Alexum
Сообщения: 582
Зарегистрирован: 2016.09.26, 10:00

Re: оптимизация количества запросов ActiveRecord

Сообщение Alexum » 2018.05.30, 10:33

an.viktory@gmail.com писал(а):
2018.05.30, 09:41
так будет правильно и оптимально ?
Model::updateAll(['id' => 3], 'time' => time());
Аргументы местами поменять.

an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

Re: оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 10:47

ElisDN писал(а):
2018.05.30, 10:26
an.viktory@gmail.com писал(а):
2018.05.30, 09:41
моя задача например обновить только одно поле в записи и не гонять по сети кучу данных.
Кучу данных?
Да если я делаю foreach кешированного массива данных например 1000 записей на удаленной базе данных получается в два раза больше запросов и на дистанции в два раза больше нагрузка на базу, разве не так ?
Последний раз редактировалось an.viktory@gmail.com 2018.05.30, 10:52, всего редактировалось 1 раз.

an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

Re: оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 10:51

Alexum писал(а):
2018.05.30, 10:33
an.viktory@gmail.com писал(а):
2018.05.30, 09:41
так будет правильно и оптимально ?
Model::updateAll(['id' => 3], 'time' => time());
Аргументы местами поменять.

Код: Выделить всё

Model::updateAll(['time' => time()], 'id' => 3);
т.е. это будет всего один запрос UPDATE table SET time=3642763742637 WHERE id=3; и все правильно ?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: оптимизация количества запросов ActiveRecord

Сообщение zelenin » 2018.05.30, 10:59

an.viktory@gmail.com писал(а):
2018.05.30, 10:51
Alexum писал(а):
2018.05.30, 10:33
an.viktory@gmail.com писал(а):
2018.05.30, 09:41
так будет правильно и оптимально ?
Model::updateAll(['id' => 3], 'time' => time());
Аргументы местами поменять.

Код: Выделить всё

Model::updateAll(['time' => time()], 'id' => 3);
т.е. это будет всего один запрос UPDATE table SET time=3642763742637 WHERE id=3; и все правильно ?
дебаг панель что показывает?

an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

Re: оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 12:21

ВАРИАНТ ПЕРВЫЙ 12 секунд 200 запросов 12 Mb памяти

Код: Выделить всё

$id_category = 3;
               $cashed_items = Synchronization::find()
                ->select('id')
                ->where(['id_category' => $id_category])
                 ->limit(100)
                ->all();
          foreach ($cashed_items as $item) {
            $item->original_date = time();
            $item->save();
 
ВАРИАНТ ВТОРОЙ 7 секунд 8 Mb 100 запросов
$id_category = 3;
$cashed_items = Synchronization::find()
->select('id,id_address, id_in_source, address_line, price,date_of_check,url,date_start,disactive')
->where(['id_category' => $id_category])
->asArray() !!!
->limit(100)
->all();

foreach ($cashed_items as $item) {
Synchronization::updateAll(['original_date' => time()],['id' => $item['id']]);
}


ИТОГО: экономия ВСЕГО в два раза;

Аватара пользователя
Alexum
Сообщения: 582
Зарегистрирован: 2016.09.26, 10:00

Re: оптимизация количества запросов ActiveRecord

Сообщение Alexum » 2018.05.30, 12:35

Вы видимо не до конца понимаете что и для чего нужно использовать.
1) ActiveRecord в виде объекта это когда нужна валидация, поведения и работа в ООП стиле. В rules модели может быть прописан валидатор проверки связанных данных. Т.е. при сохранении ваша модель может стучаться к таблице категорий и проверять, что там есть категория с id = 3.
2) при updateAll() никакой валидации не осуществляется. События beforeSave и afterSave не вызываются. Грубо говоря из модели берётся название таблицы и строится запрос update.
3) в вашем примере непонятно зачем вообще вытаскивать записи из БД, если можно сделать всего 1 запрос на их обновление.

Код: Выделить всё

Synchronization::updateAll(['original_date' => time()],['id_category' => $id_category]);

an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

Re: оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 13:01

нет в все понимаю ... когда в базе данных около 100000 записей и нужно их сверить по 10 параметрам и за пару часов то тут возникает излишная нагрузка на сервер данный способ мне позволил съкономить время и ресурсы. Т.е. мне наличие всех преимуществ AR как раз и замедляло работу с базой, но писать самому ЧИСТЫЕ SQL запросы не удобно. Данное решение позволило иметь преимущевтва AR без лишних проверок экономя ресурсы.

an.viktory@gmail.com
Сообщения: 407
Зарегистрирован: 2016.09.05, 23:21

Re: оптимизация количества запросов ActiveRecord

Сообщение an.viktory@gmail.com » 2018.05.30, 13:04

Alexum писал(а):
2018.05.30, 12:35

3) в вашем примере непонятно зачем вообще вытаскивать записи из БД, если можно сделать всего 1 запрос на их обновление.

Код: Выделить всё

Synchronization::updateAll(['original_date' => time()],['id_category' => $id_category]);
Здесь ну указано тело foreach там куча проверок, обновления будут разные в зависимости от данных.

andku83
Сообщения: 797
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: оптимизация количества запросов ActiveRecord

Сообщение andku83 » 2018.05.30, 13:10

an.viktory@gmail.com писал(а):
2018.05.30, 13:04
Здесь ну указано тело foreach там куча проверок, обновления будут разные в зависимости от данных.
чем меньше вы расскажите подробностей, тем больше неподходящих решений вам предложат

mkramer
Сообщения: 529
Зарегистрирован: 2014.12.14, 13:02

Re: оптимизация количества запросов ActiveRecord

Сообщение mkramer » 2018.05.30, 13:17

Если обновления разные в зависимости от данных, то по одним запросом и не получится, скорее всего. Разве что мутить уже на SQL с if-ами сложный запрос UPDATE руками.

andku83
Сообщения: 797
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: оптимизация количества запросов ActiveRecord

Сообщение andku83 » 2018.05.30, 13:32

Код: Выделить всё

INSERT INTO mytable (id, a, b, c)
VALUES (1, 'a1', 'b1', 'c1'),
...
ON DUPLICATE KEY UPDATE id=VALUES(id),
...

skynin
Сообщения: 154
Зарегистрирован: 2017.12.12, 10:09

Re: оптимизация количества запросов ActiveRecord

Сообщение skynin » 2018.06.13, 17:31

an.viktory@gmail.com писал(а):
2018.05.30, 13:01
когда в базе данных около 100000 записей и нужно их сверить по 10 параметрам и за пару часов
то любые ORMы будут гонять лишние данные. ActiveRecord еще няшка в сравнении с Hibernate/Doctrine
an.viktory@gmail.com писал(а):
2018.05.30, 13:01
писать самому ЧИСТЫЕ SQL запросы не удобно
тогда гоняйте данные :)

писать SQL еще не самый нижний уровень.
в сценариях работы "100000 записей и нужно их сверить по 10 параметрам" чтобы не молотило часами пишутся хранимые процедуры, для элементарых действий, с которых и набирается SQL код конкретного алгоритма сверки по 10ти параметрам.
мне наличие всех преимуществ AR как раз и замедляло работу с базой
для пакетных операций над данными - преимуществ у AR перед SQL и хранимыми процедурами мне сложно придумать :)
потому что для пакетных операций над данным не нужны - поведение и работа в ООП стиле
а если нужно ООП... то думаю что-то странное в дизайне приложения.
например частая операция - "изменить цены товаров ... согласно формуле 1 если ..., формуле 2 если
стоит просто трансформироваться в отдельные запросы -
применяем формулу 1 для группы товаров если ...
применяем формулу 2 для группы товаров если ...

Ускорить же работу AR конечно можно.
Во-первых проектирвать схему БД до написания первой AR модели. проектировать с учетом тех самых выборок, сверок, пакетных операций. если надо ради этого - то и денормализовать.
А потом уж писать модели.
Во-вторых заглядывать в план запроса. т.е. читать SQL и понимать что он делает :)

а если читаете и понимаете - то может и переписать SQL для таких, тяжелых в обработке случаев?
и Yii::$app->db->createCommand может и на порядок быть эффективней во время выполнения
Неврубающийся не может опознать врубающегося.

Ответить