Так вышло, что часто по работе возникает необходимость увеличения производительности. Одним из способов достижения данной цели в языках без нативной поддержки многопоточности является запуск программы в нескольких процессах для уменьшения времени обработки всех данных. Такая ситуация возникает как при работе с очередями, так и при работе с базой данных. Случай с очередями, как мне кажется, задача достаточно тривиальная: просто увеличиваем количество консюмеров. Но возникает вопрос, как распределить данные между процессами в случае с БД.
Задача — распределить данные между процессами. Цель — увеличить производительность системы без значительного повышения сложности логики.
Допустим, у нас есть следующая таблица:
И в нашей команде имеется следующий запрос на выборку данных на обновление:
после этого команда проводит какие-то расчеты, возвращает результат и завершается — все просто.
Теперь попробуем распределить данные БД между процессами:
1) Добавим в команду такие аргументы, как process_count, process_num. Где process_count — общее количество процессов, process_num — номер текущего процесса.
2) Преобразуем запрос в следующий вид:
3) Выбирем proccess_count оптимальный для сервера и начинаем запускать процессы, где process_num будет изменяться от 1 до proccess_count, при этом proccess_count оставляем неизменным.
Пример запуска (иллюстрация к 3 пункту):
В результате проделанной работы получаем достаточно простую технику распределения данных между процессами, которая может быть легко настроена на использование как на маломощных, так и на высокопроизводительных серверах.
Спасибо за внимание.
P.S.: если данных большое количество, то в SELECT запросе рекомендуется использовать курсоры для уменьшения нагрузки на память и БД, что хорошо описано в данной статье.
Задача — распределить данные между процессами. Цель — увеличить производительность системы без значительного повышения сложности логики.
Допустим, у нас есть следующая таблица:
CREATE TABLE Users (
id int,
name varchar(255),
balance int,
updatedAt datetime
)
И в нашей команде имеется следующий запрос на выборку данных на обновление:
SELECT u.name, u.balance
FROM Users u
WHERE 1
AND u.updatedAt = CURDATE() - INTERVAL 1 DAY
после этого команда проводит какие-то расчеты, возвращает результат и завершается — все просто.
Теперь попробуем распределить данные БД между процессами:
1) Добавим в команду такие аргументы, как process_count, process_num. Где process_count — общее количество процессов, process_num — номер текущего процесса.
2) Преобразуем запрос в следующий вид:
SELECT u.name, u.balance
FROM Users u
WHERE 1
AND u.updatedAt = CURDATE() - INTERVAL 1 DAY
AND MOD(u.id, :process_count) = (:process_num - 1)
3) Выбирем proccess_count оптимальный для сервера и начинаем запускать процессы, где process_num будет изменяться от 1 до proccess_count, при этом proccess_count оставляем неизменным.
Пример запуска (иллюстрация к 3 пункту):
#!/bin/bash
process_count=10
for ((process_num = 1; process_num <= ${process_count}; process_num++))
{
nohup command:calculate --process_count=${process_count} --process_num=${process_num} &>/dev/null &
}
В результате проделанной работы получаем достаточно простую технику распределения данных между процессами, которая может быть легко настроена на использование как на маломощных, так и на высокопроизводительных серверах.
Спасибо за внимание.
P.S.: если данных большое количество, то в SELECT запросе рекомендуется использовать курсоры для уменьшения нагрузки на память и БД, что хорошо описано в данной статье.