Плохо ли делать update + если нет обновленных полей — insert?
Есть таблица statistic, в ней поля date, id_user, browser, count (к примеру).
При этом используется UNIQUE KEY (date, id_user, browser) (поэтому продублировать значение не получится).
Как я делал раньше - SELECT * FROM statistic WHERE date='...', id_user=..., browser='...'; если запись существует - делал UPDATE `count`=`count`+1 WHERE ...; если нет - INSERT
Но, во-первых, из-за этого идет в два раза больше запросов (что не сильно хорошо для производительности), а во-вторых, в начале суток получалась ситуация, что пока я делал INSERT, другой запрос уже успевал сделать запись и я получал Integrity Constraint ошибки.
Но ведь суть таблицы состоит в том, что UPDATE происходят намного чаще, чем insert, а в SELECT вообще нет критичной необходимости. Можно ли делать сразу UPDATE `count`=`count`+1 WHERE date='...', id_user=..., browser='...'; и смотреть, если нет задействованных строк (количество affected rows равно нулю), после этого делать INSERT?
Это позволит избавиться от миллионов запросов SELECT.
Пока что не нашел, чем этот способ плохой. Подскажите, в чем я ошибаюсь?
Правда, от integrity constraint это меня не избавляет (придется ловить Exception в PHP-коде, но это уже такое дело), но зато избавляет от SELECT'ов.
Подскажите, какие могут быть недостатки в этом подходе и возможно ли существуют решения по-лучше?
//Да, знаю о ON DUPLICATE KEY UPDATE, но это решение исключительно для MySQL, и в MyISAM при партиционировании блокирует таблицу (если я правильно понял из StackOverflow). При 60-80 хитах в секунду - это не лучшее решение, как мне кажется.
Зачем выбрали MyISAM если у вас почти всегда запись а не чтение?
Ну вообще по хорошему да, ON DUPLICATE KEY UPDATE, т.к. один запрос явно лучше, чем два (update + insert)
Из-за транзакционной системы от множества InnoDB сильно проседает по скорости. Уже поплатился за это, пришлось в экстренном формате все переписывать, а то сайт положился. Сейчас эта система и работает на InnoDB, хватит с меня, целостность ключей не стоит падения скорости почти в два-три раза.
Может я ошибаюсь в том, что запись в MyISAM все же немного проходит быстрее? Так я сам тестировал и убедился в этом.
Прочитал, что InnoDB лучше работает на UPDATE, тогда, возможно, есть смысл дальше оставаться на нем? Даже если так, суть проблемы все же остается - о ON DUPLICATE я знаю; то нормальным ли будет подход "update"; если нет affected rows - insert?
evnuh: это я помню. Но при 100000 записях в InnoDB конвертировал около 20 минут старые таблицы; в MyISAM это заняло около 7 минут. Поэтому с INSERT все не так однозначно. А вот UPDATE, как пишут, наоборот в InnoDB быстрее. Поэтому, скорее всего, пока что заложу InnoDB в таблицы и буду использовать ON DUPLICATE KEY, а если нужно будет переехать на другую базу данных - перепишу на update+insert, если никто не напишет, что это bad practice
Андрей Павленко: что значит "лучше работает"? MyISAM быстрее выполняет каждую операцию, чем InnoDB, но это не значит, что общая производительность будет лучше. Обновил ответ. Поконфигурируйте InnoDB, может оно у вас на диск каждую транзакцию скидывает?