我有一个db表,里面有大约30k的记录。
我想一次一个地随机选择一个记录(当用户需要时),从表中删除记录,然后将其插入另一个表中。
我听说/发现做ORDER BY RAND()
可能会很慢。所以我正在使用这个算法(伪代码):
lowest = getLowestId(); //get lowest primary key id from table
highest = getHighestId(); //get highest primary key id from table
do
{
id = rand(lowest, highest); //get random number between a range of lowest id and highest id
idExists = checkIfRandomIdExists( id );
}
while (! idExists);
row = getRow (id);
process(row);
delete(id);
现在,有了3万条记录,我似乎很快得到了随机ID。然而,随着表格大小减少到15k,10k,5k,100等(可能是几个月),我担心这可能会变慢。
我可以做任何事情来使这个方法更有效,或者是否有行数我应该开始做ORDER BY RAND()
而不是这个方法? (例如,当剩下5k行时,开始执行ORDER BY RAND()?)
答案 0 :(得分:3)
您可以使用该方法获取随机ID,但不是检查它是否存在,只是尝试获取最接近的ID?
SELECT * FROM table WHERE id >= $randomId ORDER BY id LIMIT 0,1
然后,如果失败,请选择较低的。
答案 1 :(得分:3)
一种方法可能是确定记录数量并按记录选择:
select floor(count(*) * rand()) from thetable;
在限制中使用结果记录编号(例如chosenrec
):
select * from thetable limit chosenrec, 1;
答案 2 :(得分:2)
我可能会在单独的表格中推荐Fisher-Yates Shuffle。要生成此项,请创建一个表格,如:
CREATE TABLE Shuffle
(
SequentialId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
OtherTableId INT NOT NULL
)
值得注意的是,不要打扰外键约束。例如,在SQL Server中,我想用ON DELETE CASCADE
添加外键约束;如果你有一个可以在MySQL中使用的存储引擎,那就去吧。
现在,用您选择的语言:
Shuffle
表。现在,您有一个随机订单,因此您只需INNER JOIN
到Shuffle
表,然后ORDER BY Shuffle.SequentialId
即可查找第一条记录。如果您无法Shuffle
,则可以手动从ON DELETE CASCADE
删除记录。