validate() отправляет много EXISTS

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
gbushmakin
Сообщения: 31
Зарегистрирован: 2019.06.20, 12:38

validate() отправляет много EXISTS

Сообщение gbushmakin »

В общем переделываю один метод под себя, в нём обрабатывается модель, у которой путь валидации проходит через 1 из способов проверки:

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

                    foreach ($PropSiteVals as $index => $PropertySiteValues) {
                    
                        $data['Property']['PROPERTY_ID'] = $PropertySiteValues;
                        $data['Property']['SITE_ID'] = $index;

                        $modelPropSiteVal = new PropertySiteValues;
                        $modelPropSiteVal->load($data);
                        $modelsPropSiteVal[$indexPropVal][$index] = $modelPropSiteVal;
                        $valid = $modelPropSiteVal->validate();
                    }
В общем суть в том, что это перебор массива с формы (а строк их может прийти 10-20) и я заметил избыток запросов к БД с одними и теми же данными. Например:

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

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)
Эти запросы как я понял приходят из цикла foreach из строки $valid = $modelPropSiteVal->validate(). Как мне минимизировать количество запросов к одним и тем же данным?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: validate() отправляет много EXISTS

Сообщение ElisDN »

gbushmakin писал(а): 2020.05.28, 11:02 а строк их может прийти 10-20
Тогда смысла в минимизации нет.

У популярной статьи на сайте может быть миллион просмотров в день, но всего сто комментариев в неделю.

Ускорять имеет смысл именно этот миллион просмотров в день. А валидация и запись ста коммментариев в неделю на нагрузку сервера мало влияют.
gbushmakin
Сообщения: 31
Зарегистрирован: 2019.06.20, 12:38

Re: validate() отправляет много EXISTS

Сообщение gbushmakin »

ElisDN писал(а): 2020.05.28, 11:53
gbushmakin писал(а): 2020.05.28, 11:02 а строк их может прийти 10-20
Тогда смысла в минимизации нет.

У популярной статьи на сайте может быть миллион просмотров в день, но всего сто комментариев в неделю.

Ускорять имеет смысл именно этот миллион просмотров в день. А валидация и запись ста коммментариев в неделю на нагрузку сервера мало влияют.
Ну 10-20 строк и в каждой по 3 значения. А это получается 20х3 = 60 уже. 60 значений будет проверяться на валидацию. Может быть и 50. И 100 в будущем. Вы считаете что не стоит смотреть на количество запросов? Ведь мне единственно что не нравится, что запросы одинаковые все. Так должна работать валидация?

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

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)

SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=1)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=2)
SELECT EXISTS(SELECT * FROM `sites_attached` WHERE `sites_attached`.`ID`=3)
skynin
Сообщения: 400
Зарегистрирован: 2017.12.12, 10:09

Re: validate() отправляет много EXISTS

Сообщение skynin »

Как уже сказали, запросы от валидаторов оптимизировать обычно смысла нет.

Вообще, учитывая что типичные нагрузки - это много читаем и редко пишем - оптимизировать нужно "много читаем". а все что связано с записью - пусть будет неэфективно с точки зрения БД, это не критично. Да, если весь цикл обернуть в транзакцию - запись данных обычно отрабатывает быстрее.

Обычно используется какой-то кеш запросов у БД, встроенный, как query_cache (у MySQL < 8 и MariaDB) или наружный, типа ProxySQL. Есть такой и для Postgress. Поэтому одинаковые запросы на чтение - вообще не будут доходить до движка БД.

Но если хочется, то как всегда, превращаем работу в цикле в одну пакетную операцию
В данном случае пишем свой валидатор, который сформирует один запрос на валидацию для массива моделей.

Либо, так как проверки в основном одинаковые, валидатор с состоянием, который будет обращаться к БД только если не знает ее ответа на набор данных. Такой валидатор проще варианта, навскидку - всего лишь добавить static переменную в функцию валидации, которая будет хранить ответы БД. ключами будут данные. параметры запросов.

Но все же, подумайте, стоит ли усложнять код.
Не желайте странного, и не будет у вас головной боли чтобы достичь этого странного.
Тем более что окажется что оно вам и не нужно было, странное это.
Ответить