Sql при Model::findOne()
Sql при Model::findOne()
Здравствуйте! Заметил, что при вызове Model::findOne([]) или Model::find()->one() записывается запрос "select * from my_table" без limit'a. И лишь потом в коде (\yii\db\Command::queryOne()) из запроса возвращается первая строка. Разве не получается, что база данных будет пытаться просмотреть и получиться все возможные записи, а не остановиться при первой? Можете объяснить, в чем я ошибаюсь?
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
Так и получается... не ошибаетесь.
Нравится Yii? Давайте сделаем его лучше!.
Re: Sql при Model::findOne()
Александр, а этот момент специально упустили для того, чтобы была поддержка разных баз данных?
Стоит ли заморачиваться сейчас ставя вручную limit или же что-то будет меняться, например в yii\db\mysql\QueryBuilder?
Я понимаю, что при маленьком количестве записей такая оптимизация не имеет особого смысла, но при больших таблицах она же ощутима, верно?
ps: И при этом вся прелесть короткой записи Model::findOne($id) теряется при превращении в Model::find()->where['id'=>$id]->limit(1)->one();
ps2: А ведь помимо же основных запросов, есть еще has_one связи...
Стоит ли заморачиваться сейчас ставя вручную limit или же что-то будет меняться, например в yii\db\mysql\QueryBuilder?
Я понимаю, что при маленьком количестве записей такая оптимизация не имеет особого смысла, но при больших таблицах она же ощутима, верно?
ps: И при этом вся прелесть короткой записи Model::findOne($id) теряется при превращении в Model::find()->where['id'=>$id]->limit(1)->one();
ps2: А ведь помимо же основных запросов, есть еще has_one связи...
Re: Sql при Model::findOne()
Здесь же по первичному уникальному ключу ищется. СУБД это знает и дальше не идёт.
Re: Sql при Model::findOne()
Так есть ситуации, когда не по первичному ключу ищется, а по параметрам: чтобы далеко не ходить - таблица с пользователями {id,username, password}
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
Выборки типа ->one() без where() очень редкая штука.
Нравится Yii? Давайте сделаем его лучше!.
Re: Sql при Model::findOne()
да не важно.Sam Dark писал(а):Выборки типа ->one() без where() очень редкая штука.
Если дело обстоит как описывает автор, то есть запросы делаются без limit, то это очень странно и неинтуитивно.
Re: Sql при Model::findOne()
Как я понимаю предполагается, что разработчики будут использовать индексы чтобы решить проблему производительности
Re: Sql при Model::findOne()
ifelse писал(а):Как я понимаю предполагается, что разработчики будут использовать индексы чтобы решить проблему производительности
Код: Выделить всё
select * from my_table
Re: Sql при Model::findOne()
Упс, перепутал
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
Как часто вам нужен один пост из таблицы без каких-либо условий?
Нравится Yii? Давайте сделаем его лучше!.
Re: Sql при Model::findOne()
а это так важно? От частоты необходимости мне одного поста зависит неочевидность решения? Если так, то ответ: довольно часто.Sam Dark писал(а):Как часто вам нужен один пост из таблицы без каких-либо условий?
Думаем дальше: условие where create_time < now() сделает запрос на один пост или все-таки на все?
Re: Sql при Model::findOne()
и в правду странно, а почему нельзя во фреймворке добавить limit(1), чтоб не переживать что, казалось бы простой запрос может "завистнуть" ?
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
Это важно потому как если вы выбираете один пост, в условии уже будет where id = x или что-то подобное. Если там подобного условия нет, скорее всего имеется ошибка в логике, которую лучше заметить сразу обратив внимание на тормоза, чем потом вылавливать долгим и нудным дебагом.
Нравится Yii? Давайте сделаем его лучше!.
Re: Sql при Model::findOne()
что-то подобное я уже написал в предыдущем комменте. Любой where кроме primary key вернет больше одной записи.Sam Dark писал(а):Это важно потому как если вы выбираете один пост, в условии уже будет where id = x или что-то подобное.
автор поста заметил ошибку в логикеSam Dark писал(а):Если там подобного условия нет, скорее всего имеется ошибка в логике, которую лучше заметить сразу
Я не понимаю, зачем вы оправдываете баг в функции? Либо для этого должна быть объективная причина, либо это баг в коде. Объективной причины вы не привели.
Я часто использую Model::find()->where('name = value')->one() для проверки наличия (или отсутствия) хотя бы одной записи с данным name, но даже не подозревал что таким запросом выбирал ВСЕ записи (если конечно автор поста прав - я не проверял). Где тут ошибка логики?
Re: Sql при Model::findOne()
А при чем здесь наличие или отсутствие условий? Мы же начали говорить о получении именно одной записи и оптимизации этого запроса.
Не важно по первичному ключу, по другому ли условию, или же получение связной модели...
Если говорить об страховке на поиск ошибок, на случай если в запросе не будет условий - в каких ситуациях это может быть?
Наличие тормозов не обязательно, даже при наличии ошибки. При этом если знаем, что в базе много данных - то выдергивать все подряд для полной обработки без итераторов и/или лимита - чистое самоубийство. Если нужно всего несколько строк - то лимит и так проставим.
То есть остаются ситуации, где нужно выбрать одну запись:
- Если какая-то переменная в условие принимает не то значение - отсутствие лимита здесь не спасет - будет просто выбрано ненужное множество записей - о чем сразу и увидим.
- И если пишем метод, где условия проставляются в зависимости от ситуаций - здесь и так ошибок может быть много с самими условиями.
Но проставив лимит вручную (зная что автоматом его фреймворк не поставит) - да будет тяжко, не спорю.
Еще остаются выборки количества записей.. Здесь да - ошибки логики трудно отлавливать, но здесь и лимиты не нужны.
И сейчас, получается, при текущей ситуации, даже при правильном условии - база в любом случае будет выдергивать все что может попадать под условия - то есть затормаживается даже если правильно работает.
Не важно по первичному ключу, по другому ли условию, или же получение связной модели...
Если говорить об страховке на поиск ошибок, на случай если в запросе не будет условий - в каких ситуациях это может быть?
Наличие тормозов не обязательно, даже при наличии ошибки. При этом если знаем, что в базе много данных - то выдергивать все подряд для полной обработки без итераторов и/или лимита - чистое самоубийство. Если нужно всего несколько строк - то лимит и так проставим.
То есть остаются ситуации, где нужно выбрать одну запись:
- Если какая-то переменная в условие принимает не то значение - отсутствие лимита здесь не спасет - будет просто выбрано ненужное множество записей - о чем сразу и увидим.
- И если пишем метод, где условия проставляются в зависимости от ситуаций - здесь и так ошибок может быть много с самими условиями.
Но проставив лимит вручную (зная что автоматом его фреймворк не поставит) - да будет тяжко, не спорю.
Еще остаются выборки количества записей.. Здесь да - ошибки логики трудно отлавливать, но здесь и лимиты не нужны.
И сейчас, получается, при текущей ситуации, даже при правильном условии - база в любом случае будет выдергивать все что может попадать под условия - то есть затормаживается даже если правильно работает.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
zelenin
Если мы хотим одну запись, а условия формируем такое, что выборка даёт больше, нет ли тут логической ошибки программиста?
Если мы хотим одну запись, а условия формируем такое, что выборка даёт больше, нет ли тут логической ошибки программиста?
Ошибка тут в том, что вам нужно проверить существование. Для этого в API есть http://www.yiiframework.com/doc-2.0/yii ... s()-detail который выбирает соответствующим оптимальным запросом только результат, а не данные, которые в данном случае вам совершенно не нужны.Я часто использую Model::find()->where('name = value')->one() для проверки наличия (или отсутствия) хотя бы одной записи с данным name, но даже не подозревал что таким запросом выбирал ВСЕ записи (если конечно автор поста прав - я не проверял). Где тут ошибка логики?
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Sql при Model::findOne()
yujin1st
Одна «первая попавшаяся из выбранных» запись нужна настолько редко, что если это случилось, скорее всего тут ошибка программиста, чем она действительно нужна.
Одна «первая попавшаяся из выбранных» запись нужна настолько редко, что если это случилось, скорее всего тут ошибка программиста, чем она действительно нужна.
А почему она принимает не то значение? Не лучше ли исправить логику формирования этого значения, а не пытаться облегчить последствия оставляя логику неверной?- Если какая-то переменная в условие принимает не то значение - отсутствие лимита здесь не спасет - будет просто выбрано ненужное множество записей - о чем сразу и увидим.
Нет: https://stackoverflow.com/questions/384 ... ique-fieldИ сейчас, получается, при текущей ситуации, даже при правильном условии - база в любом случае будет выдергивать все что может попадать под условия - то есть затормаживается даже если правильно работает.
Нравится Yii? Давайте сделаем его лучше!.
Re: Sql при Model::findOne()
Что за прием дискуссии? Странно, что вы не пытаетесь вникнуть, ища логическую ошибку в ЧАСТНОМ примере.Sam Dark писал(а):zelenin
Если мы хотим одну запись, а условия формируем такое, что выборка даёт больше, нет ли тут логической ошибки программиста?
one() означает, что я хочу выбрать ОДНУ запись, а не ВСЕ, с последующей фильтрацией.
Re: Sql при Model::findOne()
мне нужна в виджете одна запись не старее пяти дней.Sam Dark писал(а):yujin1st
Одна «первая попавшаяся из выбранных» запись нужна настолько редко, что если это случилось, скорее всего тут ошибка программиста, чем она действительно нужна.
->where('time > ' . (time() - 5*60*60*24))->one()
Логическая ошибка? Или может оно мне не нужно? Так продакт-менеджеру и скажу: Yii core developer считает, что тебе это не нужно.