Вопрос возник на почве того, что я пилил AR с уклоном на то, чтобы хранить первоначальные значения по select и потом при update сверять их с текущим состоянием объекта, выбирать только те, которые изменились и выполнять запрос ТОЛЬКО с изменёнными столбцами. Теперь вводная: Один человек пояснил мне, что я занимался ерундой: не нужно делать никаких сравнений и выборок отличий, а просто делать update всей записи (всех столбцов), потому что мускул ИГНОРИРУЕТ столбцы, в которых не изменилось значение. Теперь мой вопрос-рассуждение 1. Как наука смотрит на то, что при таком предложенном варианте производится ХОЛОСТОЙ запрос к БД даже, если не было изменений (у меня такого апдейта не происходит: есть кое-где метод getAfter() который делает save и возвращает данные в вид, этот метод работает всегда, у меня если нет изменений, то save не сделает update, так как нет массива изменённых значений, запроса не будет) 2. Как наука смотрит на то, что при таком предложенном варианте в строке запроса будет присутствовать апдейт айдишника (мы ведь типа все ведь столбцы берём ) то есть получится такой вот цирк - update user set id = ?, login = ? where id = ? 3. Ну и самый главный вопрос: Если, как говорит мой товарищ, мускул при апдейте игнорирует столбцы, в которых значения не изменялись, то как он это делает? Просто проходит мимо или перезаписывает их, то есть ПРОИСХОДИТ ЛИ физическое действие с носителями (hdd, ssd)? Прокомментируйте, пожалуйста
Это легко проверить. Таблица лежит на диске в виде файла. Посчитать хэш, сделать запрос, и снова посчитать.
таблица: a = 1, b = 2 запрос: update ... set a = 1, b = 3 столбец b изменился, тут всё понятно как мускул проигнорировал столбец a? перезаписал его или проверил, что в апдейте такое же значение и ФИЗИЧЕСКИ ничего не делал на носителе?
Это не текстовый файл, где если что-то заменить на то же самое ничего не изменится. Данные будут записаны в конец, если будут. Там где это знать важно заводят столбец с значением по умолчанию CURRENT_TIMESTAMP
Вот а тебе не фиолетово? Просто запомни, что он действует именно так. И всякие мегавелосипедыи вокруг этого строить не нужно
и как ты проверишь CURRENT_TIMESTAMP ??? CURRENT_TIMESTAMP один раз пишется, а если у тебя CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, то метка разная и естественно произойдёт физическая запись на диск, ты не уловил наверное суть вопроса --- Добавлено --- происходит ли физическое воздействие на носитель, если я в столбец со значением 1 пишу значение 1, как мускул игнорирует такой столбец?
Если бы перезаписывал, то это было бы трудно назвать «ерундой» На самом деле по-любому не ерунда. Далеко не везде это работает так, как в мускуле. Плюс, если ты по-любому делаешь предвыборку, можно экономить обратный траф к серверу БД. Куча нашего софта работает подобным образом. И никто не заикается, что это «ерунда» --- Добавлено --- В частности так отсекаются полностью холостые update'ы, когда ты вообще не отвлекаешь сервер БД впустую.
ничего не понял если я сделал выборку, получил column = 1, ничего ему не менял и сделал update ... set column = 1, то что мускул сделает с column?
В стартовом посте ты вроде не сомневался в словах чела по поводу объяснения, почему «ерунда» Другие посты не читал, сорри. --- Добавлено --- Чел прав в том, что мускул делает примерно так же, как это делал ты. Но не совсем прав в том, что раз так, то самому это делать не нужно.
В стартовом посте я привёл 3 пункта сомнений, по поводу того, что я НЕ СОМНЕВАЛСЯ в чьих-то словах, там ничего я не писал. Это МНЕ человек поясняет, что искать изменения в объекте перед сохранением - это ерунда. Я считаю, что нужно сохранять только изменённые значения и если предварительно происходить холостой апдейт, то ВООБЩЕ ЕГО НЕ ПРОИЗАОДИТЬ, не делать запрос, не ставить его в очередь... и т.д. И считать так буду до тех пор, пока мне не скажут, что мускул не делает ПЕРЕЗАПИСЬ, если он ТУПО ПЕРЕЗАПИСЫВАЕТ неизменённые столбцы своими же значениями, то мне и нахер не упёрлось перепиливать AR свою
См. приписку к моему пред. посту. И в след. раз лучше искать ответы по поводу поведения мускула в его доках, а не на форуме
@miketomlin да-да, прочитал приписку: короче как понимаю ТЕБЯ Я мне нужно сделать так: если нет изменений и где-то лежит холостой апдейт, то подвергнуть его проверке и не производить его а если есть изменения, то не возиться с выборкой именно изменённых столбцов, но апдейтить весь объект ну вроде догнал, спс --- Добавлено --- @miketomlin просто у меня сделано так Спойлер: Супер-пупер-мега-ГК PHP: <?php namespace core\base; use core\Db; abstract class Model { public $id; public $original_properties = []; private static $table_names = []; public function __construct() { $properties = (array)$this; unset($properties['original_properties']); $this->original_properties = $properties; } public static function count() { return Db::pdo('select count(*) from ' . self::table())->fetchColumn(); } private static function table() { if (!isset(self::$table_names[static::class])) { $class_name = substr(strrchr(static::class, '\\'), 1); $table_name = strtolower(preg_replace('~(?<!^)[A-Z]~', '_$0', $class_name)); self::$table_names[static::class] = "`{$table_name}`"; } return self::$table_names[static::class]; } public static function countBy($params, $values = []) { return Db::pdo('select count(*) from ' . self::table() . ' where ' . $params, $values)->fetchColumn(); } /** @return static */ public static function findOne($id) { return current(Db::pdo('select * from ' . self::table() . ' where `id` = ?', [$id], static::class)); } /** @return static */ public static function findOneBy($params, $values = []) { return current(Db::pdo('select * from ' . self::table() . ' where ' . $params . ' limit 1', $values, static::class)); } public static function findAll() { return Db::pdo('select * from ' . self::table(), [], static::class); } public static function findAllBy($params, $values = []) { return Db::pdo('select * from ' . self::table() . ' where ' . $params, $values, static::class); } public function save() { $current_properties = (array)$this; unset($current_properties['original_properties']); $properties_diff_array = array_diff_assoc($current_properties, $this->original_properties); if ($properties_diff_array) { foreach ($properties_diff_array as $name => $value) { $params[] = "`{$name}` = ?"; $values[] = $value; $this->original_properties[$name] = $value; } $params = implode(', ', $params); if ($this->id) { $values[] = $this->id; Db::pdo('update ' . self::table() . ' set ' . $params . ' where `id` = ?', $values); } else { Db::pdo('insert into ' . self::table() . ' set ' . $params, $values); $this->id = $this->original_properties['id'] = Db::getInstance()->lastInsertId(); } } } public function delete() { Db::pdo('delete from ' . self::table() . ' where `id` = ?', [$this->id]); unset($this->id, $this->original_properties['id']); } }
«ничего не понял» Оставь, как было. --- Добавлено --- Хотя тут важно, в какой момент ты делаешь предвыборку из БД. Если внутри save, то все норм. --- Добавлено --- А если ты сделал ее в рамках др. действия N часов/минут/секунд назад, то не норм.
@miketomlin просто у меня сделано та PHP: $user = User::findOne(1); $user->save(); // моя AR не сделает update, вообще ничего не сделает:) $user->login = 'Test'; $user->save(); // моя AR сделает update ТОЛЬКО столбца `login` вот так работает у меня у меня в таблицах есть по 30 свойств, представляешь себе какая строка запроса будет если я не буду формировать запрос только по изменённым, ради одного столбца мне крутить в массив параметров и значений всё-равно все свойства придётся, а так я только изменения беру --- Добавлено --- @miketomlin а вообще СУТЬ вопроса: что делает мускул с неизменёнными столбцами запроса? ПЕРЕЗАПИСЫВАЕТ или ПЕРЕХОДИТ К СЛЕДУЮЩЕМУ физически что мускул делает с ДИСКАМИ НА СЕРВАКЕ ЁМАЁ сколько можно повторять
Тебе на этот вопрос уже ответил какой-то чел. Я подтвердил. Это вроде в доках в статье по UPDATE'у написано. Посмотри.
я если бы нашёл, то не спрашивал бы КАЖДЫЙ ГОД НА РАЗНЫХ форумах одно и то же БЕЗ ОТВЕТА не знаешь так и скажи
Я тебе сказал, что чел правильно описал поведение мускула (НЕ перезаписывает дубли), но сделал неправильный вывод из этого.
Drunkenmunky пока что не пишет под мою диктовку А если когда-нибудь и начнет, то там все равно будет написано что-то вроде
Я ж говорю - это легко проверить. Хотя, слегка рассудив промеж себя, то чтобы исключить возможноневерные выводы, слегка усложняем проверку. Считаем хэш файла таблицы, обновляем некую запись, изменяя в ней значение, и снова считаем хэш. Сверяем. Изменился. Снова обновляем ту же строку возвращая первоначальное значение. Сверяем - если хэш вернулся в первоначальное же значение, то прекращаем опыт, ибо изначальное предположение неверно. Если же хэш новый, то снова делаем тот же запрос и снова считаем хэш. Если обновился, то обновление записи происходит, если нет, то нет.
пост 3: содержимое одного столбца изменилось, хеш изменился, содержимое другого столбца не изменялось, вывод: воздействие на носитель произошло при том, что содержимое другого столбца не изменялось - вот результат твоего способа проверки, хешь же разный )))