mysql-从数据库中随机抽取数据的分析总结

本文章只针对从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表的随机数据的时候,则会涉及到多个库的操作,在建立连接会消耗一定的时间,效率还是会有所降低的。但是整体效果还是不错的哦。该需求完成处理解决。

。。
。。
。。

有不同见解的同学,也可以进行反馈;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值