2013-08-01 5 views
6

У меня есть таблица с Первичные ключи в строке как 12a4..., c3af.... Я хочу, чтобы обрабатывать их параллельно:Разделить шестнадцатеричный индекс на n штук

process_them(1,4) on machine 1 
process_them(2,4) on machine 2 
process_them(3,4) on machine 3 
process_them(4,4) on machine 4 

Doing выше, необходимо выбрать все строки в таблице, без машин, координирующие друг с другом. Лучшая идея, которую я могу придумать, чтобы разделить их на 16, как:

select * from table where id like '1%' 
... 
select * from table where id like 'e%' 
select * from table where id like 'f%' 

Есть ли лучшая идея, что позволяет мне больше расколов, как 1/2, 1/4, 1/8, 1/16, 1/32 и т. Д. Из всех строк?

Примечание: Я делаю это, чтобы обрабатывать данные пользователя в ночное время и отправлять им уведомление. Я ничего не редактирую в самой БД. И мы должны обрабатывать тысячи пользователей за раз, его нельзя разделить мелкозернистым способом, так как он не будет эффективным таким образом.

+0

Если машины имеют инкрементирующий идентификатор системы, они могут использовать это в предложении LIMIT. Но это, вероятно, считается «координацией». ИМХО, чтобы достичь чего-то лучшего, чем то, что вы предлагаете, им нужно что-то знать об окружающей среде. – mabi

+0

Я думаю, что распределенная база данных - лучшее решение. – Suleman

ответ

0

Самый простой подход будет добавление status столбец в таблицу, по крайней мере, в двух состояниях:

0 = pending 
1 = *not* pending 

Тогда каждая обработка резьбы будет в состоянии «резерв» небольшой пакет строк для их обработки. Общий рабочий будет:

BEGIN TRANSACTION; 
SELECT * FROM queue WHERE status = 0 LIMIT 5 FOR UPDATE; -- load 5 pending items 
-- if no pending item: terminate here 
-- save this list of jobs in your application layer here 
UPDATE queue SET status = 1 WHERE id IN (@id_list); -- list of id's from the previous step 
COMMIT; 
-- process your jobs here 
-- loop 

В зависимости от фактического времени обработки заданий, этот подход может быть слишком тяжелым накладные расходы, чтобы быть удовлетворительным. Увеличьте LIMIT на первом шаге, чтобы загружать больше заданий за раз, чтобы снизить относительные накладные расходы за счет, возможно, менее сбалансированного распространения заданий по всем процессам.

+0

Мы не обновляем сами данные. И одновременный 'select for update', который будет блокировать друг друга до фиксации/прерывания. Это не будет сделано параллельно. – aitchnyu

+0

Нет, в худшем случае параллельные потоки будут заблокированы только в тот момент, когда один поток загружает задания и обновляет их статусы ('SELECT' и' UPDATE'), то есть несколько миллисекунд, если таблица правильно индексируются. Обратите внимание, что часть «обрабатывать ваши рабочие места здесь» находится за пределами транзакции. Я не уверен, что добавление и манипулирование новым столбцом для вашей операции следует рассматривать только как «изменение самих данных», но я понимаю, что в некоторых случаях это может быть нехорошо. – RandomSeed

2

Отличные идеи ...

вы можете использовать MD5 хэш distrubute строк в разумном хорошо распределенным образом быстро, consitently (Там никогда не будет пропущенный ряд) и без изменений DDL.

*let n = number of desired partitions. Use the following sql to 
*let s = salt, expirementally chosen to provide the best distribution based on key allocation pattern. 
SELECT * FROM TABLE WHERE mod(cast(conv(md5(concat(s, Priamry_Key)), 16, 10), n) = 0; 
SELECT * FROM TABLE WHERE mod(cast(conv(md5(concat(s, Priamry_Key)), 16, 10), n) = 1; 
... 
... 
SELECT * FROM TABLE WHERE mod(cast(conv(md5(concat(s, Priamry_Key)), 16, 10), n) = (n-1); 

Этот подход, который я видел, реализован в производственных условиях несколько раз с хорошими результатами.

SQL здесь не проверен Я не делаю никаких gaurantee на sytax.

Смежные вопросы