<rmcreative>

RSS

MySQL, REPLACE INTO и ON DUPLICATE KEY UPDATE

23 декабря 2012

В MySQL есть два расширения, которые позволяют атомарно вставить или обновить запись. Годятся они для штук с довольно высокой нагрузкой, когда без блокировок не работает типичный сценарий:

  1. Выбрать запись.
  2. Если выбралась — обновить.
  3. Если пусто — вставить.

REPLACE

REPLACE INTO
  vote
SET
  user_id = 13,
  object_id = 42,
  value = 7

INSERT INTO ON DUPLICATE KEY UPDATE

INSERT INTO
  vote
SET
  user_id = 13,
  object_id = 42,
  value = 7
ON DUPLICATE KEY UPDATE
  value = 7

Сходства

И то и то выражение в итоге даст примерно тот же результат. При нарушении ограничения на уникальность (то есть UNIQUE KEY или PRIMARY KEY) не будет никакой ошибки. Для ключа user_id, object_id в базе будет единственная запись с значением 7.

Отличия

Кроме очевидного отличия в синтаксисе есть и очень важно отличие в том, как всё это работает. REPLACE при срабатывании ограничения удаляет запись (и вызывает ON DELETE CASCADE) и затем вставляет новую, что не так быстро, как ON DUPLICATE KEY UPDATE, который обновляет запись без удаления.

Комментарии RSS

  1. №7298
    Максим
    Максим 24 дек. 2012 г., 0:25:36

    Там еще с автоинкремент тонкость вроде была.

  2. №7299
    ostin
    ostin 24 дек. 2012 г., 0:47:47

    Немного тавтология, но такой вариант немного более универсальный:

    ON DUPLICATE KEY UPDATE
      value = VALUES(value)
  3. №7300
    sergunik
    sergunik 24 дек. 2012 г., 12:50:50

    Вже писав про такі інсерти - sergunik.name/?p=393

  4. №7302
    vasa_c
    vasa_c 24 дек. 2012 г., 13:48:35

    здесь не только в скорости разница. если есть какие-то поля (не указанные в запросе) со значениями отличными от DEFAULT, то UPDATE их не затронет. А REPLACE вставит новую запись с уже DEFAULT-значениями.

  5. №7365
    Илья
    Илья 08 янв. 2013 г., 19:10:40

    не подскажите из каких соображений отсутствуют соответствующие метод для моделей в YII?

    довольно часто они были необходимы. в итоге использовал данное решение www.askdev.ru/php/4199/Yii-Расширить-CActiveRecord/

  6. №7372
    Sam
    Sam 09 янв. 2013 г., 19:11:33

    Отсутствует потому как это специфичная для MySQL штука, а в Yii всё более-менее универсальное: работает для MySQL, SQLite, PostgreSQL, MSSQL и Oracle.

  7. №7447
    Александр
    Александр 26 янв. 2013 г., 14:30:05

    Если не ошибаюсь – INSERT INTO ON DUPLICATE KEY UPDATE увеличивает AUTO_INCREMENT.

  8. №7700
    zedget
    zedget 18 марта 2013 г., 15:54:43

    vasa_c метко подметил - ON DUPLICATE KEY UPDATE в большинстве случаев - более верное решение.

  9. №8337
    Duss
    Duss 09 сент. 2013 г., 13:02:00

    "Если не ошибаюсь – INSERT INTO ON DUPLICATE KEY UPDATE увеличивает AUTO_INCREMENT." Как раз наоборот т.к.

    "REPLACE при срабатывании ограничения удаляет запись (и вызывает ON DELETE CASCADE) и затем вставляет новую"

  10. №8348
    Lacmus
    Lacmus 11 сент. 2013 г., 12:07:43

    "Если не ошибаюсь – INSERT INTO ON DUPLICATE KEY UPDATE увеличивает AUTO_INCREMENT." - только для InnoDB таблиц

  11. №10246
    masha777
    masha777 02 февр. 2016 г., 21:55:05

    привет всем. а какой метод самый быстрый?

  12. №11113
    Дмитрий Дегтярев
    Дмитрий Дегтярев 23 нояб. 2017 г., 12:06:34

    "Там еще с автоинкремент тонкость вроде была."

    Пришлось столкнуться, и вот оно как:

    INSERT INTO ON DUPLICATE KEY UPDATE: На INNODB увеличивает AUTO_INCREMENT. На MyISAM AUTO_INCREMENT не меняется. Lacmus прав.

    REPLACE: И на INNODB и на MyISAM AUTO_INCREMENT меняется. Более того, измененная запись меняет значение автоинкрементного поля. Например, если id у записи был 2, то после замены легко может стать 10. Все из-за удаления существовавшей записи и создания такой же новой, с другим id.

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.