本文章只针对从mysql随机抽取数据进行方法分析,和总结
项目需要通过表名获取随机数据进行数据校验工作,所以有这个随机从数据库拉数据的需求;
通过查询资料和网友们的博客等都未能很好解决需求问题,接下来针对网上的方法进行分析和总结,并给出自己最优的解决方案;
直接进入主题:
mysql随机抽取数据方法汇总
1.第一种:
select * from `table`
order by rand() limit 1;
分析:该种抽取数据的方法,可以达到效果,但是运行效率非常低,在百万级别下运行时间超长,无法满足需求。
2.第二种:
SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (
(SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id LIMIT 1;
分析:该种方法相比第一种效率非常高,基本在0.几秒内能查询获取到的数据
优点:速度非常快,在千万级数据下,随机查询获取一条数据的时间为0.161s;
缺点:无法一次性获取多条,当把limit改写成10000之后,获取到的数据是连续的,无法满足需要的随机性。
3.第三种:
SELECT * FROM `table` WHERE id >= (ROUND(((( SELECT MAX( id ) FROM `table`)-( SELECT MIN( id ) FROM `table`)) * RAND()),0) + ( SELECT MIN( id ) FROM `table`))
LIMIT 1;
分析:该种方法相比于第一种方法效率非常高,跟第二种方法执行效率差不多;能基本满足随机性要求,但是当将limit 改成100或者10000的时候,数据出现连续一段范围内的随机数,而不是全量数据里面的随机。
优点:速度非常快,在千万级数据下,随机查询一条的时间为0.116s,能获取随机性多条数据;另外当数据的ID不连续之后,通过该方法能一次性获取200;数据库会自动排除不存在的ID;
缺点:在数据量达千万级别时,limit变成10000之后,数据还是随机的,但是会相对性的限制在一定范围内,当limit改成200之后,ID随机性保存在1-100000之间的随机性,达不到需求的全量随机性;导致该问题的原因在rand()函数;但是当我将最多id和最小id取出来自己做了操作之后,查询效率变慢了 ;
4.第四种:
采用程序生成随机ID,并查询获取的方式
具体方法:
①:通过表名获取最大ID和最小ID值
②:生成随机数方法:
public class NumberUtil {
public static void main(String[] args) {
//0-10之内,随机取五个数
List<Integer> integers = randomCommon(1, 1496255, 200);
if (integers != null && integers.size() != 0) {
for (int i : integers) {
System.out.println(i + ",");
}
} else {
System.out.println("kk");
}
}
/**
* 随机指定范围内N个不重复的数
*
* @param min 指定范围最小值
* @param max 指定范围最大值
* @param n 随机数个数
* @return
*/
public static List<Integer> randomCommon(int min, int max, int n) {
List<Integer> integers = new ArrayList<Integer>();
if (min < 0) {
min = 0;
}
if ((max - min) + 1 < n) {
n = (max - min) + 1;
}
if (max < min) {
max = min;
}
if (max < 0 || n < 0) {
return integers;
}
for (int i = 1; i <= n; i++) {
int randomNumber = (int) Math.round(Math.random() * (max - min) + min);
if (integers.contains(randomNumber)) {
i--;
continue;
} else {
integers.add(randomNumber);
}
}
return integers;
}
}
③:通过获取到的ID,进行数据查询,在该方法内为了避免数据ID不连续问题,当中有两种方法可选:
第一种:通过上述第三种方法进行数据获取;
第二种:通过扩大随机范围获取数据,在从获取到的数据,在通过中位数从中间往两端获取数据达到随机数据的需去,部分代码如下:
通过以上步骤满足项目需求,如果只对一张table进行数据随机获取,该方法效率还算可观;
当需要对N张table进行数据获取操作,则可以通过stream.parallelStream并发进行获取数据,有兴趣的可以自行进行查找资料学习一下,在要获取N张table表的随机数据的时候,则会涉及到多个库的操作,在建立连接会消耗一定的时间,效率还是会有所降低的。但是整体效果还是不错的哦。该需求完成处理解决。
。。
。。
。。
有不同见解的同学,也可以进行反馈;