MySQL 获取随机数据方法

 本文介绍了MySQL 获取随机数据方法。
两种方法(一种使用 mysql 解决,一种使用 php 处理。推荐后者)。

1、order by rand()
数据多了极慢,随机性非常好,适合非常小数据量的情况。

2、SELECT * FROM table_name AS r1 JOIN (SELECT (ROUND(RAND() * (SELECT ABS(MAX(id)-MIN(id)-$limit) FROM table_name))+(SELECT MIN(id) from table_name)) AS id) AS r2 WHERE r1.id >= r2.id ORDER BY r1.id ASC LIMIT $limit;

速度非常快,但是得到的数据是id连续的,没办法解决。
子查询产生一个随机数。
rand()是0到1的随机数,可以等于0到1。
MAX(id)-MIN(id)还要要减去$limit以免结果数量不够$limit条
因为主表id可能不连续,所以r1.id要>=r2.id
还要注意的是有时候最小id不是从1开始的,可能从一个很大的数开始,所以必须加上M(id)的值
手册相关内容:若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1))。例如, 若要在7 到 12 的范围(包括7和12)内得到一个随机整数, 可使用以下语句:
SELECT FLOOR(7 + (RAND() * 6));
3、select * from test where rand()<0.0005 limit 10;

0.0005是一个计算出的比例直接关系到随机的质量,比如数据表10000条数据,需要随机取300条,那么0.0005就需要改成(300/10000=0.03)。
这种方法不能保证每次能取到多少,需要取多次。这个应该是要扫表。几百万的数据量速度是非常快的。

百万级别2和3速度一样的快,主要区别是2总能返回limit条数据,3就没准了(符合正太分布)。2是连续数据,3是随机行。

3的话用1亿和3亿数据测试都在1分钟左右
mysql> select count(*) from gameLogin;
+-----------+
| count(*) |
+-----------+
| 277222670 |
+-----------+
1 row in set (0.00 sec)

mysql> select id from gameLogin where rand()<0.0000001;
+-----------+
| id |
+-----------+
| 15431983 |
| 68236783 |
| 83237035 |
| 98697590 |
| 151502399 |
| 166502644 |
| 181963230 |
| 234768030 |
| 249768278 |
| 265228883 |
+-----------+
10 rows in set (1 min 4.77 sec)

 2的话理论上和数据量没关系,不过没有测试。用PHP随机id然后in()是没有性能损耗的
 
mysql> select * from gameLogin where id in(15431983 , 68236783 ,  83237035 , 98697590 , 151502399 , 166502644 ,181963230 , 234768030 , 249768278 ,265228883);
+-----------+----------+--------+----------+---------------------+----------------+
| id | uid | gameId | serverId | loginTime | loginIp |
+-----------+----------+--------+----------+---------------------+----------------+
| 15431983 | 30379812 | 1 | 794 | 2011-08-02 07:53:41 | |
| 68236783 | 1953934 | 1 | 1233 | 2012-04-17 06:21:00 | |
| 83237035 | 6121220 | 1 | 1491 | 2012-06-18 22:22:55 | |
| 98697590 | 39005535 | 1 | 1865 | 2012-08-27 14:22:53 | |
| 151502399 | 37553560 | 22 | 3776 | 2013-03-02 19:55:32 | 125.66.206.209 |
| 166502644 | 45051088 | 21 | 1201 | 2013-05-05 20:32:06 | 124.128.93.100 |
| 181963230 | 45812185 | 22 | 6116 | 2013-07-04 11:18:10 | 115.238.43.146 |
| 234768030 | 45453939 | 22 | 5778 | 2013-12-19 05:27:29 | 60.222.209.151 |
| 249768278 | 47917487 | 22 | 11852 | 2014-02-21 08:30:30 | 113.8.177.80 |
| 265228883 | 4022820 | 1 | 4573 | 2014-05-06 23:21:09 | |
+-----------+----------+--------+----------+---------------------+----------------+
10 rows in set (0.08 sec)
4、推荐使用PHP解决。尽量少用mysql去处理问题。
交给php解决 不操作mysql 比如 一千w条数据 随机取十条 先用php生成一千万以内的随机数 20个 再用mysql的主键in(这20个随机数) 之所以取20条是因为有些id可能被删除了 然后再用php处理成10条。性能最高

0 个评论

要回复文章请先登录注册