从Mysql某一表中随机读取n条数据的SQL查询语句

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

从 Mysql 表中随机读取数据不难,方法还挺多的,但是如果要考虑效率,得到一个快速的高效率的方法,那就不是一件简单的事情了(至少对我来说不简单)。

语句简单,速度慢的方法
SELECT * FROM table_name ORDER BY rand() LIMIT 5;

语句复杂,速度快的方法
SELECT * FROM table_name AS r1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM table_name)) AS id) AS r2 WHERE r1.id >= r2.id ORDER BY r1.id ASC LIMIT 5;


cjc注: ... AS id) AS t2 这里的 id, 也许该换成id2, 后面 WHERE t1.id >= t2.id 改成  WHERE t1.id >= t2.id2

摘自: http://www.dayanmei.com/blog.php/ID_203.htm

******************************************************************************************


Discuz中,随机读取论坛的几个连续主题:

PHP里调用:
s="SELECTtid,fid,subjectFROM$tableprethreadsASr1JOIN(SELECTROUND(RAND()(SELECTMAX(tid)FROM$tableprethreads))ASid)ASr2WHERE(fid=13)and(r1.tid>=r2.id)ORDERBYr1.tidLIMIT6";query = db>query(s);       

phpMyAdmin 中测试语句:
SELECT tid, fid, subject FROM cdb_threads AS r1 JOIN (SELECT ROUND(RAND()*(SELECT MAX(tid) FROM cdb_threads)) AS id) AS r2 WHERE (fid=13) and (r1.tid >= r2.id) ORDER BY r1.tid LIMIT 6

注意: 不可删除 order by r1.tid, 否则总会固定出现最初的2行数据 


******************************************************************************************

另一文章里使用了MIN()的版本:

通用语句:

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;


cjc注: ... AS id) AS t2 这里的 id, 也许该换成id2, 后面 WHERE t1.id >= t2.id 改成  WHERE t1.id >= t2.id2

Discuz 语句:

SELECT tid, fid,subject
FROM `cdb_threads` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(tid) FROM `cdb_threads`)-(SELECT MIN(tid) FROM `cdb_threads`))+(SELECT MIN(tid) FROM `cdb_threads`)) AS id) AS t2
WHERE t1.tid >= t2.id and fid=13 ORDER BY t1.tid LIMIT 5;


or

s="SELECTFROM$tableprethreadsASt1JOIN(SELECTROUND(RAND()((SELECTMAX(tid)FROM$tableprethreads)(SELECTMIN(tid)FROM$tableprethreads))+(SELECTMIN(tid)FROM$tableprethreads))ASid)ASt2WHERE(t1.tid>=t2.id)and(fid=13)ORDERBYt1.tidLIMIT6";query = db>query(s);       

cjc注: MIN(tid) 得到的通常是1, 所以加上MIN()的计算,不一定有必要.



***************************  全文转贴如下 ******************************************************
原文网址: http://jnote.cn/blog/mysql/mysql-rand-efficiency.html

mysql使用rand随机查询记录效率测试 - 八月 8, 2007 | Posted by 老蒋

一直以为mysql随机查询几条数据,就用

SELECT * FROM `table` ORDER BY RAND() LIMIT 5

就可以了。
但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上

查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。

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


搜索Google,网上基本上都是查询max(id) * rand()来随机获取数据。

SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id ASC LIMIT 5;
但是这样会产生连续的5条记录。解决办法只能是每次查询一条,查询5次。即便如此也值得,因为15万条的表,查询只需要0.01秒不到。

上面的语句采用的是JOIN,mysql的论坛上有人使用

SELECT *
FROM `table`
WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` )
ORDER BY id LIMIT 1;
我测试了一下,需要0.5秒,速度也不错,但是跟上面的语句还是有很大差距。总觉有什么地方不正常。

于是我把语句改写了一下。

SELECT * FROM `table`
WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`)))  
ORDER BY id LIMIT 1;
这下,效率又提高了,查询时间只有0.01秒

最后,再把语句完善一下,加上MIN(id)的判断。我在最开始测试的时候,就是因为没有加上MIN(id)的判断,结果有一半的时间总是查询到表中的前面几行。
完整查询语句是:

SELECT * FROM `table`
WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`)))  
ORDER BY id LIMIT 1;

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;


最后在php中对这两个语句进行分别查询10次,
前者花费时间 0.147433 秒
后者花费时间 0.015130 秒
看来采用JOIN的语法比直接在WHERE中使用函数效率还要高很多。
此方法limit如果大于1,返回的结果会是连续的记录。

本文转自博客园知识天地的博客,原文链接:从Mysql某一表中随机读取n条数据的SQL查询语句,如需转载请自行联系原博主。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
34
分享
相关文章
阿里云DTS踩坑经验分享系列|DTS打通SQL Server数据通道能力介绍
SQL Server 以其卓越的易用性和丰富的软件生态系统,在数据库行业中占据了显著的市场份额。作为一款商业数据库,外部厂商在通过解析原生日志实现增量数据捕获上面临很大的挑战,DTS 在 SQL Sever 数据通道上深研多年,提供了多种模式以实现 SQL Server 增量数据捕获。用户可以通过 DTS 数据传输服务,一键打破自建 SQL Server、RDS SQL Server、Azure、AWS等他云 SQL Server 数据孤岛,实现 SQL Server 数据源的流动。
69 0
阿里云DTS踩坑经验分享系列|DTS打通SQL Server数据通道能力介绍
MySQL的架构与SQL语句执行过程
MySQL架构分为Server层和存储引擎层,具有高度灵活性和可扩展性。Server层包括连接器、查询缓存(MySQL 8.0已移除)、分析器、优化器和执行器,负责处理SQL语句;存储引擎层负责数据的存储和读取,常见引擎有InnoDB、MyISAM和Memory。SQL执行过程涉及连接、解析、优化、执行和结果返回等步骤,本文详细讲解了一条SQL语句的完整执行过程。
35 3
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
35 9
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
79 9
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
【YashanDB 知识库】如何将 mysql 含有 group by 的 SQL 转换成崖山支持的 SQL
在崖山数据库中执行某些 SQL 语句时出现报错(YAS-04316 not a single-group group function),而这些语句在 MySQL 中能成功执行。原因是崖山遵循 SQL-92 标准,不允许选择列表中包含未在 GROUP BY 子句中指定的非聚合列,而 MySQL 默认允许这种操作。解决办法包括:使用聚合函数处理非聚合列或拆分查询为两层,先进行 GROUP BY 再排序。总结来说,SQL-92 更严格,确保数据一致性,MySQL 在 5.7 及以上版本也默认遵循此标准。
MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等