Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Приветствую всех!
Если вопрос поднимался - киньте ссылку, пожалуйста, не смог найти.
Есть метод increment(), позволяющий увеличить значение ячейки в БД на N.
У меня в записи в БД требуется увеличить на 1 значение 2 столбцов сразу.
Делать 2 запроса (2 последовательных инкремента) не хочется - глупо как-то.
Как можно это реализовать одним запросом к базе средствами Laravel?
Не в сети
Перенесите локигу из уровня приложения в бд (триггеры) или транзакции
Не в сети
Здравствуйте,а Вам принципиально нужен increment() ? Такой вариант не устроит?
DB::table('users')
->where('id', 1)
->update([
'column1' => DB::raw('column1 + 1'),
'column2' => DB::raw('column2 + 1'),
]);
Не в сети
Не в сети
Благодарю всех ответивших!
lodar
про триггеры думал, но хотел сделать все через php
Ocnelias
спасибо, тоже хороший вариант
AlexeyMezenin
"глупым" он мне кажется из-за лишнего запроса к базе, хотя грязный sql позволяет сделать апдейт 1 запросом.
А теперь главное - может кто-нибудь объяснить какой из 3 вариантов лучше и почему? Просто, возможно, у них есть какие-либо плюсы/минусы.
1)триггеры
2)DB::table('users')
->where('id', 1)
->update([
'column1' => DB::raw('column1 + 1'),
'column2' => DB::raw('column2 + 1'),
]);
3) increment();
increment();
Заранее благодарю за помощь.
Не в сети
А есть ещё вариант разобраться с постановкой задачи. Трудно рассуждать вот так на "абстрактных сферических конях", но подобные вопросы периодически возникают на около-SQL-ных форумах. Я несколько раз видел как вопрощающий приходит к выводу, что не стоит оптимизировать то, что не должно было родиться.
Расскажи пожалуйста что хранится в этих полях.
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
Не в сети
А теперь главное - может кто-нибудь объяснить какой из 3 вариантов лучше и почему? Просто, возможно, у них есть какие-либо плюсы/минусы.
Плюс двух increments() в поддерживаемости и читаемости кода. Если тебя настолько беспокоит тот микроскопический оверхед двух increment() перед сырым запросом, то Laravel явно не для твоего проекта. Установи Laravel Debugbar, посмотри сколько времени Laravel тратит на обработку всего запроса и посмотри сколько времени тартится на два increment() и сколько на сырой запрос.
Не в сети
AlexeyMezenin, убедили спасибо. Сам склонялся к тому, что экономлю на спичках, но иногда стремление к чрезмерно оптимизации берет верх...
Еще раз всем спасибо!
Не в сети
Если тебя настолько беспокоит тот микроскопический оверхед двух increment() перед сырым запросом
Совершенно не обязательно он будет микроскопическим. Как сказал artoodetoo, нужно знать специфику - время запроса как минимум зависит от условия; если там WHERE primary_key = ?, то запросы пройдут быстро, а если условие сложнее - то вместо задержки N (на один запрос с двумя increment) на пустом месте получаем N*2 (два запроса, по одному на один increment).
Дальше, кроме собственно поиска нужной строки для изменения (по WHERE), ее изменение требует блокировки (в MyISAM так вообще всей таблицы). Если запрос один - блокировка делается только один раз. При большом числе клиентов (нагруженный ресурс) каждая блокировка это дополнительные задержки, причем не только для того, кто изменяет строку, но и для читающих клиентов (ведь многие операции - такие, например, как, SELECT COUNT(*) - блокируют всю таблицу).
Может быть также ситуация, когда один запрос БД может обработать эффективнее, чем два отдельных (раскидать в разные потоки, обновить индексы за один проход, а не за два, и прочее). Разбивая запросы вы лишаете БД возможности их оптимизировать.
Кроме того, БД может быть на другом хосте и вне зависимости от типа запроса на каждый отдельный запрос будет происходить задержка (latency), что, опять же, на пустом месте дает вместо M времени M*2.
К тому же, мы не знаем - может быть проблемный запрос вообще выполняется в цикле.
Вывод следующий: предоптимизации - зло, но если есть очевидный способ убрать задержки, это не сильно ухудшает читаемость и не требует дополнительных усилий (как в данном случае - вариант Ocnelias) - то этот способ нужно использовать. В конечном счете, проект состоит из десятков, а то и сотен, запросов, и если к каждому относится как "микроскопический оверхед" - то в будущем есть нехилый риск столкнуться с ситуацией, когда все в целом будет тормозить, при том, что отдельные части, вроде бы, работают быстро.
Установи Laravel Debugbar, посмотри сколько времени Laravel тратит на обработку всего запроса
...и обнаружь в production, что запрос на локальной базе в 100 записей проходит за 0.01 мс, а на реальной в 100000 записей с 1000 клиентов - внезапно - за 1+ с.
Не в сети
предоптимизации - зло, но если есть очевидный способ убрать задержки, это не сильно ухудшает читаемость и не требует дополнительных усилий - то этот способ нужно использовать. В конечном счете, проект состоит из десятков, а то и сотен, запросов, и если к каждому относится как "микроскопический оверхед" - то в будущем есть нехилый риск столкнуться с ситуацией, когда все в целом будет тормозить, при том, что отдельные части, вроде бы, работают быстро
Волновать должны только запросы в БД на один HTTP запрос. В реальных Laravel приложениях 95% функционала вообще приходится на админку или панель управления пользователя, где скорость запросов в БД стоит на 25 месте. Вот в остальных 5% и надо смотреть что бы оптимизировать. Но не до, а уже когда возникнет медленный запрос, который в реальных условиях возникает ну очень редко (Laravel - это больше про MVP). Там уже смотреть что и как оптимизировать. Если будут напрягать два increment(), то тогда, скорее всего, проблему сырым запросом уже и не решить и нужно будет кардинально менять подход к решению этой задачи.
Так что, предоптимизации - зло.
Не в сети
Страницы 1