MySQL RAND()函数

本文探讨了MySQL中实现随机数据抽取的不同方法及其效率对比。通过实验发现,使用RAND()函数结合MAX(id)的方式能显著提高查询速度,并指出使用JOIN语法可能降低效率。
  • 由于需要大概研究了一下MySQL的随机抽取实现方法。如:要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。

  • 但是,在MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面不能使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。
    You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.

  • 但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。

  • 开启mysql的profiling变量,可以查看sql语句的执行时间。(具体对MySQL变量的认知参考我的另一篇文章MySQL变量

mysql> show variables like "%pro%";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| profiling                | ON    |

msqyl> set profiling=1;
mysql> show profiles;
+----------+------------+------------------------------------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                                                      |
+----------+------------+------------------------------------------------------------------------------------------------------------+                                                                                       |
|        7 | 0.00039500 | select * from test as t1 join (select ROUND(RAND()*(select MAX(id) from test)) as id) as t2 on t1.id>t2.id |
|        8 | 0.00050100 | select * from test as t1 join (select ROUND(RAND()*MAX(id)) as id from test) as t2 on t1.id>t2.id          |
|        9 | 0.00029700 | select * from test where id> (SELECT ROUND( MAX(id) * RAND()) FROM test )                                  |
|       11 | 0.00022700 | select * from test where id> (SELECT ROUND(RAND()*(select MAX(id) FROM test)))                             |
+----------+------------+------------------------------------------------------------------------------------------------------------+

我执行的分别是一下四条语句:

mysql> select * from test as t1 join (select ROUND(RAND()*(select MAX(id) from test)) as id) as t2 on t1.id>t2.id;
+----+-----+-----+-----------+------+
| id | age | sex | name      | id   |
+----+-----+-----+-----------+------+
|  6 |   0 |   0 | 个        |    5 |
|  7 |   1 |   1 | 第三方     |    5 |
|  9 |   1 |   1 | 阿斯顿飞   |    5 |
| 10 |   1 |   1 | 张        |    5 |
+----+-----+-----+-----------+------+
4 rows in set (0.00 sec)


mysql> select * from test as t1 join (select ROUND(RAND()*MAX(id)) as id from test) as t2 on t1.id>t2.id;
+----+-----+-----+-----------+------+
| id | age | sex | name      | id   |
+----+-----+-----+-----------+------+
|  5 |   1 |   1 | 王        |    4 |
|  6 |   0 |   0 | 个        |    4 |
|  7 |   1 |   1 | 第三方     |    4 |
|  9 |   1 |   1 | 阿斯顿飞   |    4 |
| 10 |   1 |   1 | 张        |    4 |
+----+-----+-----+-----------+------+
5 rows in set (0.00 sec)

mysql> select * from test where id> (SELECT ROUND( MAX(id) * RAND()) FROM test );
+----+-----+-----+----------+
| id | age | sex | name     |
+----+-----+-----+----------+
|  3 |   1 |   1 | 萨芬      |
|  5 |   1 |   1 | 王        |
|  6 |   0 |   0 | 个        |
|  9 |   1 |   1 | 阿斯顿飞   |
| 10 |   1 |   1 | 张        |
+----+-----+-----+-----------+
5 rows in set (0.00 sec)



mysql> select * from test where id> (SELECT ROUND(RAND()*(select MAX(id) FROM test)));
+----+-----+-----+--------------+
| id | age | sex | name         |
+----+-----+-----+--------------+
|  3 |   1 |   1 | 萨芬         |
|  4 |  78 |   0 | 的           |
|  5 |   1 |   1 | 王           |
|  7 |   1 |   1 | 第三方       |
|  9 |   1 |   1 | 阿斯顿飞     |
| 10 |   1 |   1 | 张           |
+----+-----+-----+--------------+
6 rows in set (0.00 sec)

可以看到:
1. SELECT ROUND(RAND()*(select MAX(id) FROM test

SELECT ROUND( MAX(id) * RAND()) FROM test
要快;
2. 采用JOIN的语法比直接在WHERE中使用函数效率要低

但是最后我还有个问题:

大家可以看到我的前两个用了join的语句的返回结果里,表里数据后面几条id为6 7 9 10,但是第3条语句结果里没有id=7和4那条数据,第4条语句结果里没有id=6那条数据。
不知各位老铁怎么看。咕~~(╯﹏╰)b

<think>好的,我现在需要处理用户关于MySQLRAND函数的使用说明和示例教程的查询。首先,我得回顾一下自己对RAND函数的了解,确保信息的准确性。记得RAND()函数主要用于生成0到1之间的随机浮点数,可能还支持种子参数。但用户可能需要更详细的信息,比如具体语法、示例以及常见应用场景。 接下来,我需要检查用户提供的引用内容。引用[1]和[2]都提到了使用ORDER BY RAND()来随机排序查询结果,比如SELECT * FROM employee_tbl ORDER BY RAND();。这确实是RAND函数的一个典型应用,但需要注意性能问题,尤其是处理大数据表时可能会比较慢。另外,用户可能还想知道如何生成不重复的随机数或者如何结合其他函数使用,比如ROUND()来生成整数随机数。 然后,我应该组织信息结构,按照用户的要求分点说明。首先介绍基本用法,包括语法和生成随机数的例子。然后讨论ORDER BY RAND()的应用,但也要提醒性能问题,并建议替代方法,比如使用固定偏移量。接下来,可以介绍如何生成特定范围的随机数,比如0-100之间的整数,这需要结合ROUND和乘法运算。还要提到RAND(N)种子参数的作用,用于生成可重复的随机数序列。 此外,用户可能需要了解生成不重复的随机数的方法。虽然RAND()本身每次调用都会产生不同的结果,但如果需要不重复的序列,可能需要更复杂的处理,比如先随机排序再选取前N条记录,或者使用唯一标识符结合哈希函数。不过,引用中没有提到这些,可能需要参考其他资料,但要注意避免超出用户提供的引用范围。 同时,要确保所有数学表达式符合格式要求,行内表达式用$...$,独立公式用$$...$$。例如,生成0到100的整数可以用$ROUND(RAND() * 100)$。另外,示例代码需要用反引号包裹,并注明语言类型,如```sql。 在生成相关问题部分,需要考虑用户可能进一步会问的问题,比如如何优化ORDER BY RAND(),或者如何生成特定范围的随机数,以及种子的应用场景。还要注意是否有性能优化技巧,比如在应用层处理随机化而不是数据库层。 最后,检查是否有遗漏的信息,确保回答覆盖了基本用法、示例、常见应用、注意事项以及相关问题。同时,确认引用标识正确添加,例如在提到ORDER BY RAND()时引用[^1]和[^2]。需要确保每个引用只在第一次提到时标注,避免重复。</think>### MySQL RAND函数使用说明 #### 1. 基本语法与功能 MySQL的`RAND()`函数用于生成一个$0 \leq x < 1$的随机浮点数。其语法支持两种形式: - `RAND()`:生成完全随机的数值 - `RAND(N)`:当指定种子值$N$时,生成可重复的伪随机序列 示例: ```sql SELECT RAND(); -- 输出类似0.123456789 SELECT RAND(100); -- 固定种子生成固定值 ``` #### 2. 典型应用场景 **(1) 随机排序查询结果** 通过`ORDER BY RAND()`可实现数据随机排序: ```sql SELECT * FROM employee_tbl ORDER BY RAND(); -- 每次执行返回不同排序结果[^1][^2] ``` *注意:该方式在数据量较大时性能较差,建议改用应用层随机化或添加固定偏移量。* **(2) 生成特定范围的随机数** 结合数学运算生成指定范围的随机值: ```sql SELECT ROUND(RAND() * 100); -- 生成0-100的整数 SELECT FLOOR(5 + RAND() * 10); -- 生成5-14的整数 ``` **(3) 随机抽样数据** ```sql SELECT * FROM table_name ORDER BY RAND() LIMIT 10; -- 随机抽取10条记录 ``` #### 3. 生成不重复随机数 通过组合`RAND()`与唯一标识字段实现: ```sql SELECT id, RAND() as rand_val FROM table_name ORDER BY rand_val; -- 利用随机值排序实现不重复抽样 ``` #### 4. 性能优化建议 - 对于海量数据,避免直接使用`ORDER BY RAND()` - 改用预计算随机值字段并建立索引: ```sql ALTER TABLE table_name ADD COLUMN random_val FLOAT DEFAULT RAND(); CREATE INDEX idx_random ON table_name(random_val); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值