Часть системы, над которой я сейчас работаю, включает в себя журнал в mysql, с часто обновляемым счетчиком.
Вставляемые данные имеют формат:
date | name | count |
-----------+------+-------+
2009-01-12 | alan | 5 |
2009-01-12 | dave | 2 |
2009-01-12 | mary | 1 |
Эти данные регулярно анализируются из плоского файла, обобщенного, как указано выше, при подготовке к вставке / обновлению базы данных - уникальный ключ в базе данных - это пара (date, name).
Раньше эта система проверяла существующую таблицу на предмет любых записей для данной пары date и name, прежде чем принимать решение об обновлении или вставке.
Проблема, с которой мы сталкиваемся, заключается в том, что по мере роста этой таблицы время отклика не улучшается, и мы хотим максимально сократить количество запросов.
Система была недавно обновлена для выполнения запроса INSERT ... ON DUPLICATE KEY UPDATE, что незначительно уменьшило количество select, но наш общий случай на некотором расстоянии - это update.
Мне интересно, знает ли кто-нибудь о функции mysql, которая, по сути, INSERT ... ON DUPLICATE KEY UPDATE в обратном порядке, то есть попытается обновить строку, если нет совпадений, выполните вставку?
Я не слишком ясно дал понять, что я хотел бы сделать, например, когда у меня есть запись ('2009-01-12','alan','5'):
UPDATE table SET count = count+5 WHERE date = '2009-01-12' and name = 'alan';
и если вышеуказанное не помогает, вставьте вышеуказанные данные. Необходимость увеличения счетчика - вот почему REPLACE не работает. Replace выполняет удаление и вставку и не позволяет вам ссылаться на удаляемую строку, поэтому count = count + 5 не будет увеличивать предыдущее значение count на 5.
@jasoncohen - INSERT ... ON DUPLICATE KEY UPDATE выполняет свою работу, но я спрашиваю, есть ли более оптимальный способ сделать это.
Приносим извинения за путаницу, вызванную плохой формулировкой оригинала!


Почему недостаточно INSERT? Даже если в большинстве случаев это дублированный ключ и, следовательно, обновление (а не наоборот), это все равно правильная операция, верно?
Вы просто спрашиваете о производительности?
Используйте функцию ЗАМЕНИТЬ:
Это то же самое. При использовании «UPDATE ... ON NO KEY INSERT» движку базы данных все равно придется сначала проверить, есть ли что-то для обновления. Следовательно, нет необходимости в отдельной конструкции, даже если обновление является наиболее распространенным.
Было бы неплохо использовать пример.
Было бы неплохо попросить @HelgaIliashenko сначала попросить пример использования, прежде чем голосовать против.
Я решил проголосовать против, система попросила меня прокомментировать это, что я и сделал. Теперь я не могу отказаться от своего голоса против. Извини за это.
@HelgaIliashenko Не вижу, какой пример вы ищете. В частности, возникает вопрос о том, нужен ли альтернативный синтаксис по соображениям производительности, и гипотетическое UPDATE ON NO KEY не повлияет на производительность. Какой пример вы ищете?
Я пытался выяснить, что именно вы хотите, и, насколько я понимаю, вы не хотите ничего делать, если данные совпадают? Я не вижу решения для этого, если «счетчик» каким-то образом изменится и потребует обновления, вы застряли с INSERT INTO ON DUPLICATE KEY UPDATE (с которым я действительно не вижу проблемы).
Однако, если счетчик никогда не будет обновлен, вы можете изучить INSERT IGNORE INTO, который проигнорирует вставку, если уникальный ключ (дата + имя) уже существует.
Вы не рассматривали возможность «промывки / вращения» плоского файла только для проверки наличия добавленного материала? Или это невозможно?
Редактировать:
INSERT немедленно завершится ошибкой из-за нарушения повторяющегося ключа и в этом случае вызовет UPDATE. Не должно быть никаких проблем с производительностью. Я делаю это все время с довольно большой базой данных, и я не заметил большой разницы в производительности при запуске с пустой базы данных в отличие от уже заполненной базы данных.
Однако, вероятно, неплохо время от времени запускать ANALYZE TABLE / OPTIMIZE TABLE, чтобы поддерживать индекс в хорошем состоянии.
Имеет смысл, я просил больше в надежде, чем ожидал, что для этого будет какой-то волшебный, сверхэффективный запрос mysql!