网站首页 > 技术文章 正文
每晚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(id) FROM 表名))) ORDER BY id LIMIT 10;
如果使用以上的SQL语句,发现查询到的数据是连续的,但我们要的是随机的,不难理解 LIMIT 10 得到当前查询条件的前10条,所以是相对连续的,uid 是自增的,因为用的是储存插入的,实际项目也是相对连续的。这条SQL 一次性查询无法达到我们的需求,则可分别一条条查询,如果要求的随机条数较多,不推荐采用这条SQL语句了。
但以上的随机有个缺陷,那就是数据源被限制在一个范围里,而不会在1000W数据里随机。那要是调整成
SELECT * FROM 表名 WHERE id> ROUND(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,空挡的情况下,尽可能平均分布的随机呢?
对此,不知你有没有更好的方案,欢迎交流,一起学习,一起进步。
猜你喜欢
- 2024-10-27 MySQL左查询最全介绍(sql 左查询)
- 2024-10-27 mysql查询指定父级下所有子级(mysql根据子节点查父)
- 2024-10-27 MySQL数据库入门(七)多表查询及大量练习
- 2024-10-27 mysql进行数据查询(单表查询)(mysql 查询数据表)
- 2024-10-27 【执行计划】MySQL如何执行查询?(mysql执行查询语句)
- 2024-10-27 MySQL查询列必须和group by字段一致吗?
- 2024-10-27 查看MySQL所有数据库列表(mysql怎么查看数据库列表)
- 2024-10-27 「mysql」mysql调优时必须掌握的慢查询语句排查命令
- 2024-10-27 MySQL进阶实战7,查询的执行过程(mysql查询机制)
- 2024-10-27 说说 MySQL 子查询(在mysql中子查询是)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)