Так вышло, что часто по работе возникает необходимость увеличения производительности. Одним из способов достижения данной цели в языках без нативной поддержки многопоточности является запуск программы в нескольких процессах для уменьшения времени обработки всех данных. Такая ситуация возникает как при работе с очередями, так и при работе с базой данных. Случай с очередями, как мне кажется, задача достаточно тривиальная: просто увеличиваем количество консюмеров. Но возникает вопрос, как распределить данные между процессами в случае с БД.

Задача — распределить данные между процессами. Цель — увеличить производительность системы без значительного повышения сложности логики.

Допустим, у нас есть следующая таблица:

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 запросе рекомендуется использовать курсоры для уменьшения нагрузки на память и БД, что хорошо описано в данной статье.