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

qod*_*nja 9 mysql random recordset

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

我正在使用的表有600万条记录(并且正在增长),ID会自动递增,但并不总是存储在表中(非无间隙).

我已经尝试过推荐的LIMIT 1查询,但查询需要永远运行 - 考虑到记录中存在空白,有没有快速的方法来执行此操作?我不能只采取最大值并随机化范围.

更新:

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

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

更新:

这个查询有点快 - ish.仍然不够快= /

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
Run Code Online (Sandbox Code Playgroud)

cri*_*ian 8

SELECT * FROM TABLE ORDER BY RAND() LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

好的,这很慢.如果你要搜索ORDER BY RAND() MYSQL,你会发现很多结果说这很慢,情况就是这样.我做了一些研究,我发现这个替代MySQL rand()在大型数据集上很慢, 我希望这样做更好


小智 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
;
Run Code Online (Sandbox Code Playgroud)

可以将1000改为10000或者根据需要改变......

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

select ID from table
  where (ID % 1000) = floor(rand() * 1000)
  order by rand()
  limit 1
;
Run Code Online (Sandbox Code Playgroud)

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

编辑2:

请参阅:从MySQL中的表中选择随机行的最佳方法是什么?

这可能是最快的方法:

select @row := floor(count(*) * rand()) from some_tbl;
select some_ID from some_tbl limit @row, 1;
Run Code Online (Sandbox Code Playgroud)

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