Задать вопрос

Как ускорить UPDATE MySQL?

У меня есть следующая проблема.
В скрипте есть
"""
SELECT id FROM 
    table
WHERE
    time_login < %s
ORDER BY time_last_login ASC
LIMIT 1 FOR UPDATE
""" % time_threshold

time_login = unixtime метка
time_threshold = int(time.time()) - (5 * 60)

Сразу же после этого запроса есть
time_last_login = int(time.time())
        update_time_query = "UPDATE table SET time_last_login = %s WHERE id = %s"
        cursor.execute(update_time_query, (time_last_login, id))
        connection.commit()


Делаю для того, чтобы отпустить строку от FOR UPDATE.
Теперь проблема, с каждым запросом растет время выполнения скрипт.
Начинается с 0.34 сек и доход до 41 секунды.
Запросов в секунду 200, строк в таблице 33000
Специально для этого был взят выделенный сервер (Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz, 64 ОЗУ, 1 ТБ SSD)
Но запросы все так же медленно выполняются.

mysql конфиг

[mysqld]
disable-log-bin
innodb_buffer_pool_size = 48G
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
max_heap_table_size = 256M
sql-mode =
tmp_table_size = 256M
transaction-isolation = READ-COMMITTED
default-authentication-plugin = mysql_native_password
mysqlx = OFF
performance-schema = ON
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1

# New Settings
max_connections = 2000000
thread_cache_size = 2000
table_open_cache = 20000
table_open_cache_instances = 16
open_files_limit = 100000
max_allowed_packet = 256M
innodb_lock_wait_timeout = 600
innodb_spin_wait_delay = 96

# Recommendations
skip-name-resolve = ON
sort_buffer_size = 16M
read_rnd_buffer_size = 16M
join_buffer_size = 16M
performance-schema = ON
innodb_redo_log_capacity = 12G
innodb_buffer_pool_instances = 50

# Additional settings
innodb_io_capacity = 4000
innodb_log_file_size = 8G
innodb_flush_neighbors = 0
innodb_thread_concurrency = 0
innodb_read_io_threads = 16
innodb_write_io_threads = 16
# Дополнительные параметры для улучшения производительности
innodb_flush_log_at_timeout = 1
innodb_max_dirty_pages_pct = 90
innodb_max_dirty_pages_pct_lwm = 10
innodb_lru_scan_depth = 2048
innodb_io_capacity_max = 10000

# Дополнительные настройки
innodb_adaptive_hash_index = ON
innodb_change_buffering = all
innodb_log_buffer_size = 512M
table_definition_cache = 2000


Подскажите что могу сделать?
  • Вопрос задан
  • 1449 просмотров
Подписаться 4 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 5
petermzg
@petermzg
Самый лучший программист
Блокировка "for update" работает только внутри транзакции.
И не работает с autocommit.
Делайте явный START TRANSACTION
Ответ написан
Комментировать
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
Индекс на id можете сделать.

А ещё можете помедитировать над запросом
EXPLAIN UPDATE table SET time_last_login='%s' WHERE id='%s'
, цифры подставьте сами.
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
Проверте что построен индекс по полю time_last_login
Ответ написан
opium
@opium
Просто люблю качественно работать
Если у вас 200 запросов на апдейт в секунду и всего 33к записей, перейдите на редис или любой аналог многопоточный если нужен перформанс в сотовые секунды
Ответ написан
Комментировать
@otlejal
Как минимум использовать асинхронный драйвер mysql. Как максимум перейти на постгрес и увеличить кэш. Разработчикам тапалок привет)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы