基础问题:我有一个表main
,其中包含近百万行。我希望对main
中的每一行执行一些操作,并将结果存储在results
表中。
由于涉及表的大小几乎所有引用两个表的查询都很慢。
由于涉及的处理量很大,我需要多个客户端并行处理数据。
我做了什么:所以,为了加快速度,我有一个todo
表,其结构与main
相同。每个客户端进程从todo
中随机选择一行,工作大约需要30秒,然后从todo
中删除该行。
随机选择的查询是:
SELECT todo.id, todo.tag
FROM todo JOIN
(SELECT
(SELECT MIN(id) FROM todo) + (RAND() *
(SELECT MAX(id) - MIN(id) FROM todo)
) AS val --All this to get a random number between min and max
) AS r2
WHERE todo.id >= r2.val
ORDER BY id ASC
LIMIT 1
请参阅,例如MySQL select 10 random rows from 600K rows fast和http://jan.kneschke.de/projects/mysql/order-by-rand/。
我所做的事情的问题:我收到了很多“碰撞”(即main
中同一行的多个结果条目。单词,多个客户端几乎同时处理相同的信息。这是可以的,因为db可以支持它(每个main的结果很多),我可以稍后进行清理,但不能正常,因为我不必要地消耗处理时间。
当我说“很多”时,我的意思是10%到15%的新条目重复。
我很怀疑这是由于MySQL RAND()
功能的问题,因为它有问题的历史,并且据说可以纠正错误。 (例如,MySQL RAND() seed values almost repeat)
然而,由于随机选择,todo
ID中不可避免地存在间隙,这种差距只会越来越大......因此使用>=
(这是当随机生成的id在间隙中时返回结果所必需的,意味着当间隙增大时,碰撞越来越可能。
那么,......如何在最小化碰撞的同时对这个过程进行并行化(并且做很少的额外工作)? (最好主要使用SQL,而不必添加插入层,例如队列服务。)