打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
期望薪资12k,有一道笔试题没有做好,面试官只给10K,要不要去?
userphoto

2022.08.02 广东

关注

如果你想第一时间收到类似的文章

点击上面↑「爱开发」关注我们

每晚10点,捕获技术思考和创业资源洞察

在MYSQL中,有一张1000W 数据记录的表,主键id是自增的,如何随机抽取10条记录?
文|洪生鹏

本文旨在抛砖引玉,具体实施方案需要自己在实践中动手去尝试,不断尝试,不断改进调优。

一张1000W 数据记录的表,数据表的主键id 是自增的,需要随机抽取10条记录。请给出解决方案。

 MYSQL中自带了随机取数据的rand()函数,如果数据量少,我们可以直接使用,效率是可以接受的。对此随机查询10条记录,我们可以这样写:

  SELECT * FROM 表名 ORDER BY RAND() LIMIT 10

 但要是遇到数据量上千万级别时,这时如果还是采用rand()函数,很明显在性能方面不乐观。

于RAND函数, api文档是这样说明的:

You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.

由此可见,rand()放在ORDER BY 子句中导致全表扫描,这样一来性能明显下降。

那么有没有办法优化呢?毋庸置疑,答案是有的。我们尝试有两种方案来看看。

方案1

尝试用子查询实现

SELECT * FROM 表名 WHERE id >= (SELECT floor(RAND() * (SELECT MAX(idFROM 表名)))    ORDER BY id LIMIT 10;  

 如果使用以上的SQL语句,发现查询到的数据是连续的,但我们要的是随机的,不难理解 LIMIT 10 得到当前查询条件的前10条,所以是相对连续的,uid 是自增的,因为用的是储存插入的,实际项目也是相对连续的。这条SQL 一次性查询无法达到我们的需求,则可分别一条条查询,如果要求的随机条数较多,不推荐采用这条SQL语句了。

但以上的随机有个缺陷,那就是数据源被限制在一个范围里,而不会在1000W数据里随机。那要是调整成

 SELECT * FROM 表名 WHERE idROUND(1+10000000*RAND()) LIMIT 10

是不是解决了,也不是,这种查询在数据表不够1000W数据的时候,会查询不到数据。

方案2

上面的方法我们是直接用MYSQL来实现,那么不妨换个思路,先用程序来实现。

我们先用程序生成10个随机数,(可能还要进行重复排除,然后再由这些随机组分十次取出int x=rand()*100000 

select * from 表名 where id>x order by id limit 1

不过事先从程序中生成这种方式仍然存在一个问题:如果ID分布不均匀的情况下,随机出来的ID可能会取不到足够的数据(这个随机数之前是通过最小值和最大值之间来随机的,但是这个数值的分布可能不均匀。比如id>xxx的数据可能取出来不够10条数据)

如果要从MYSQL入手,是否能够在MYSQL主键中随机取出10条并且能够利用到索引。在不连续id,空挡的情况下,尽可能平均分布的随机呢?

不知你有没有更好的方案,欢迎交流,一起学习,一起进步。

【END】
从《色戒》,看人性的欲望
如果不做程序员,你会选择从事什么职业谋生?
分享职场攻略、技术心得和创业资源
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
MySQL性能优化的最佳20+条经验
mysql如何让自增id归0解决方案
负载突然翻了100倍,如何拯救MySQL架构?
mysql使用与优化及ID生成方案(像清单,比较全,缺点是不说原因)
业务单表 读写缓慢 如何优化?
17.如何正确地显示随机消息undefined
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服