2013-08-01 45 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 

做上述必須選擇所有行表中,沒有機之間相互協調。我可以想出最好的辦法是將它們分成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

如果機器有一個遞增的系統ID,他們可以在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'就會互相鎖定,直到commit/abort。它不會同時完成。 – 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沒有測試我沒有在sytax上使用gaurantee。

相關問題