最近由于需要大概研究了一下MYSQL的随机抽取实现方法。举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。

但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。

但是真正测试一下才发现这样效率非常低。一个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中使用函数效率还要高很多。

参考文献:

MySQL Order By索引优化:http://www.phpq.net/mysql/mysql-order-by.html
MySQL Order By语法:http://www.phpq.net/mysql/mysql-order-by-syntax.html
MySQL Order By Rand()效率:http://www.phpq.net/mysql/mysql-order-by-rand.html
MySQL Order By用法:http://www.phpq.net/mysql/mysql-order-by-use.html

MySQL 中随机抽样:order by rand limit 的替代方案的更多相关文章

  1. MYSQL随机抽取查询 MySQL Order By Rand()效率问题

    MYSQL随机抽取查询:MySQL Order By Rand()效率问题一直是开发人员的常见问题,俺们不是DBA,没有那么牛B,所只能慢慢研究咯,最近由于项目问题,需要大概研究了一下MYSQL的随机 ...

  2. MySQL Order By Rand()效率

    最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RA ...

  3. 【MySQL性能优化】改进MySQL Order By Rand()的低效率

    <a href="http://click.aliyun.com/m/9153/">点击查看原文</a> 正 文:   最近由于需要研究了一下MYSQL的随 ...

  4. mysql中limit的用法实例解析

    mysql中limit的用法解析. 在mysql中,select * from table limit m,n.其中m是指记录开始的index,从0开始,n是指从第m条开始,取n条. 例如: mysq ...

  5. 详解MySQL中EXPLAIN解释命令

    Explain 结果解读与实践   基于 MySQL 5.0.67 ,存储引擎 MyISAM .   注:单独一行的"%%"及"`"表示分隔内容,就象分开“第一 ...

  6. ORDER BY RAND()

    大概是因为需要研究了一下MYSQL随机样本实现.例如:离tablename表随机抽取了创纪录,我们一般的写法是:SELECT * FROM tablename ORDER BY RAND() LIMI ...

  7. MySQL中UNION和UNION ALL的使用

    在数据库中,UNION和UNION ALL关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同. MySQL中的UNION UNION在进行表链接后会筛选掉重复的记录,所以在表链接后 ...

  8. MySQL中怎么对varchar类型排序问题

    MySQL中怎么对varchar类型排序问题 在mysql默认order by 只对数字与日期类型可以排序,但对于varchar字符型类型排序好像没有用了,下面我来给各位同学介绍varchar类型排序 ...

  9. MySQL的Order By Rand()的效率问题

    MySQL很多时候需要获取随机数据,举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是: 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在OR ...

随机推荐

  1. 【Java EE 学习 69 中】【数据采集系统第一天】【SSH框架搭建】

    经过23天的艰苦斗争,终于搞定了数据采集系统~徐培成老师很厉害啊,明明只是用了10天就搞定的项目我却做了23天,还是模仿的...呵呵,算了,总之最后总算是完成了,现在该好好整理该项目了. 第一天的内容 ...

  2. checkbox &amp; radio 的对齐问题

    不仅不同浏览器不同,不同的字体,不同的文字大小也会表现不一样. 重置 form checkbox & radio 因为不同浏览器解析不一样,有些是默认margin,有些是默认padding,还 ...

  3. jQuery瀑布流简单示例

    1,以下demo是基于window的滚动  

  4. BZOJ 1303 CQOI2009 中位数图 水题

    1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2340  Solved: 1464[Submit][Statu ...

  5. OC基础--block

    block与函数类似:1.可以保存代码 2.又返回值 3.有形参 4.调用方式一样 block的标志:^ 一.定义一个无参无返回值的block void (^myBlock)();--1.void 代 ...

  6. 过滤android应用列表(区分系统应用、第三方应用、sd卡中的应用)

    if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { // 系统程序 }else if ((app.flags & Applica ...

  7. [ROS]1 小乌龟

    对于一个新新新手,Linux,ROS都要学习.安装ROS真的很讨厌了,于是采用易科机器人实验室的ubuntu12.04-amd64-ros-exbot-h2-140520版本. 测试一下小乌龟节点.主 ...

  8. Studio之版本管理工具Git (图文教程)

    目前业界主流的版本管理工具主要是 svn/git.svn是1种集中式的代码管理工具,而git是1种散布式的代码管理工具,广受极客的爱好.而基于git的github更是全宇宙码农的提高逼格,深究技术的必 ...

  9. windows下的node-canvas历程

    背景:由于在前期开发的过程中,对前端的小图片采用了css-sprite,开始的时候都是在http://spritegen.website-performance.org/站点上合成图片及样式的,但是某 ...

  10. Apache虚拟主机设置

    Apache支持两种虚拟主机,一种是基于IP地址的,一种是基于域名的. 基于IP地址的虚拟机现在使用的很少,它需要一台服务器需要拥有多个IP地址.基于域名的虚拟主机要求服务器有一个IP地址就可以了,只 ...