从mysql表中快速选择随机ID,包含数百万条非连续记录

时间:2011-12-09 17:53:25

标签: mysql random recordset

我环顾四周,似乎没有任何简单的方法可以做到这一点。它几乎看起来只是抓取一部分记录并在代码中完成所有随机化(perl)。我在网上看到的方法看起来更像是数十万,但肯定不是数百万。

与我合作的表有600万条记录(并且还在增长),ID会自动递增,但并不总是存储在表格中(非无间隙)。

我已经尝试过推荐的LIMIT 1查询,但是查询需要永远运行 - 考虑到记录中存在空白,是否可以快速执行此操作?我不能只接受最大值并在范围内随机化。

更新

我的一个想法可能是获取最大值,根据最大值随机化一个限制,然后从random_limit_1到random_limit_2获取10个记录的范围,然后获取在该范围内找到的第一个记录。

或者,如果我知道最大值,有没有办法可以选择说出表的第5条记录,而不必知道它是哪个ID。然后抓住该记录的ID。

更新

这个查询有点快 - 是的。仍然不够快= /

SELECT t.id FROM table t JOIN (SELECT(FLOOR(max(id) * rand())) as maxid FROM table) as tt on t.id >= tt.maxid LIMIT 1

3 个答案:

答案 0 :(得分:8)

SELECT * FROM TABLE ORDER BY RAND() LIMIT 1;

好的,这很慢。如果你要搜索ORDER BY RAND() MYSQL,你会发现很多结果都说这很慢,而且情况确实如此。我做了一点研究,发现了这个替代MySQL rand() is slow on large datasets 我希望这更好

答案 1 :(得分:7)

是的,想法似乎很好:

select min(ID), max(ID) from table into @min, @max;
set @range = @max - @min;
set @mr = @min + ((@range / 1000) * (rand() * 1000));
select ID from table
  where ID >= @mr and ID <= @mr + 1000
  order by rand()
  limit 1
--   into @result
;

可以将1000更改为10000或根据需要进行缩放......

编辑:你也可以试试这个:

select ID from table
  where (ID % 1000) = floor(rand() * 1000)
  order by rand()
  limit 1
;

按不同的方式拆分......

编辑2:

请参阅:What is the best way to pick a random row from a table in MySQL?

这可能是最快的方式:

select @row := floor(count(*) * rand()) from some_tbl;
select some_ID from some_tbl limit @row, 1;

遗憾的是,变量不能在limit子句中使用,因此您必须使用动态查询,在代码中编写查询字符串,或使用PREPARE和EXECUTE。此外,限制n,1仍需要将n个项目扫描到表格中,因此它的速度仅为上面列出的第二种方法的两倍。 (虽然它可能更均匀,并保证始终找到匹配的行)

答案 2 :(得分:0)

SELECT ID
    FROM YourTable
    ORDER BY RAND() LIMIT 1;