最近做项目,需要做一个从 mysql 数据库中随机取几条数据出来。总所周知,order by rand 会死人的。。因为本人对大数据量方面的只是了解的很少,无解,去找百度老师。。搜索结果千篇一律。特发到这里来,供大家学习, 需要的朋友可以参考下
MySQL 是一个开放源码的小型关联式数据库管理系统,开发者为瑞典 MySQL AB 公司。MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了 MySQL 作为网站数据库。
在 mysql 中带了随机取数据的函数,在 mysql 中我们会有 rand() 函数,很多朋友都会直接使用,如果几百条数据肯定没事,如果几万或百万时你会发现,直接使用是错误的。下面我来介绍随机取数据一些优化方法。
SELECT * FROM table_name ORDER BY rand() LIMIT 5;
rand 在手册里是这么说的:
RAND()
RAND(N)
返回在范围 0 到 1.0 内的随机浮点值。如果一个整数参数 N 被指定,它被用作种子值。
- mysql> select RAND();
- -> 0.5925
- mysql> select RAND(20);
- -> 0.1811
- mysql> select RAND(20);
- -> 0.1811
- mysql> select RAND();
- -> 0.2079
- mysql> select RAND();
- -> 0.7888
你不能在一个 ORDER BY 子句用 RAND() 值使用列,因为 ORDER BY 将重复计算列多次。然而在 MySQL3.23 中,你可以做: SELECT * FROM table_name ORDER BY RAND(),这是有利于得到一个来自 SELECT * FROM table1,table2 WHERE a=b AND c
网上基本上都是查询 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 秒,速度也不错,但是跟上面的语句还是有很大差距
后来请教了 baidu, 得到如下代码
完整查询语句是:
- 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 秒
执行效率需要 0.02 sec. 可惜的是, 只有 mysql 4.1.* 以上才支持这样的子查询.
注意事项 查看官方手册,也说 rand() 放在 ORDER BY 子句中会被执行多次,自然效率及很低。
以上的 sql 语句最后一条,本人实际测试通过,100W 数据,瞬间出结果。
来源: