Как оптимизировать 1000 одновременных update строки?
Запрос:
UPDATE Task SET remains = remains - 1, last_start_msec = 16741764826702 WHERE id = 93258990;
При количестве апдейтов 1 строки 100 раз в секунду все ок. Как только количество одновременных апдейтов переваливает за 150-200 в секунду все эти запросы зависают в огромную очередь, помогает только перезапуск базы.
Запросы идут по API от клиентов. Задержка в лишнюю м.сек катастрофична.
Александр, если вы будете проверять не на равенство 0 а на меньше нуля - то логика будет работать верно. Так делают в численных методах. Вообще когда события идут таким плотным трафиком - сложно учитывать единичные.
Если вы делаете систему голосований - то тем более сложно учеть кажый единичный декремент.
Попробуйте их накапливать в сессии приложения и обновлять пакетом.
Александр, попробуйте отказаться от MySQL. Возможно вы достигли технологического предела для такой
системы и дальше нужно либо делать шардинг или какое-от разделение таблицы на независимые хосты.
Или попробуйте NoSQL системы. По сути вам подходит любая NoSQL где есть просто атомарный декремент значения по ключу. Посмотрите Tarantool, LevelDb, RocksDb,
Очень похоже на проблему XY. Без описания реальной задачи решить вряд ли получится.
И данных все равно мало, даже если неверно выбрана задача. Например, непонятно что конкретно тормозит? Обновление данных или выборка?
Отсюда неизвестно, что поможет. Быть может нужно шардирование, а может нужно кеширование в каком-нибудь Редис.
Vitsliputsli, совершенно не понятно, видно что запросы апдйета виснут и за ним все остальные.
редис и nosql методы мы используем, но в данном случае никак. только через базу.
Александр, посмотрите как выполняется select по update, если там все быстро, а скорее всего так и есть, то проблема именно в блокировках. В этом случае шардирование не спасет.
редис и nosql методы мы используем, но в данном случае никак. только через базу.
странное утверждение. не все и всегда можно сделать через базу. Да и не нужно скорее всего, многократный апдейт одного и того же это очень странное поведение, и не факт что оно нужно для решения неизвестной задачи.
Если СУБД имеет нормальное железо и нам требуется чтобы она выдерживала высокую нагрузку. То, как минимум проверьте используемые индексы, unique и foreighn keys, быть может возможно от них отказаться. Как максимум, продумать неблокирующую схему работы, например разбить эту одну обновляемую строку на несколько строк предназначенных разным запросам, поделить общий remains на несколько, тогда на начальных этапах разные запросы будут обновлять разные строки и не будет блокировок, когда remains уменьшится, то все равно будт обращаться к одним и тем же. Здесь мы потеряем в скорости select, но зато избежим блокировок на начальных этапах, если конечно remains достаточно большой. Но, все это очень усложнит работу, да и схему надо проверять, не зная других составляющих не факт, что это чтото даст,.
И, гораздо проще запихнуть это в Redis, и работать в нем, как ни крути он не пишет одно и то же по 4 раза, а если упираемся в запись на диск, то это оптимальное решение.