mysql如何在范围内随机取多个数字

[复制链接]
查看11 | 回复4 | 2021-1-27 05:23:29 | 显示全部楼层 |阅读模式
比如在0-100中随机取三个数,不重复(不能使用随机取一个,再随机取第二个判断是否重复,重复则重新取这种套环的方法)
分 -->
回复

使用道具 举报

千问 | 2021-1-27 05:23:29 | 显示全部楼层
现在我的想法是创建一个100条数据的临时表,然后orderbyrand()limit3,觉得太繁琐
回复

使用道具 举报

千问 | 2021-1-27 05:23:29 | 显示全部楼层
SELECTCEIL(RAND()*(100))fromtemp_tableorderbyrand()limit3;
回复

使用道具 举报

千问 | 2021-1-27 05:23:29 | 显示全部楼层
orderbyrand()取随机消息原理
1:创建临时表用memory引擎,有两个字段分别是double类型字段R和需要取出的字段,且没有索引
2:用rand()为每一行生成一个0到1的随机数,存入double的字段R中
3:按照R字段排序:初始化sort_buffer,将内存临时表一行一行取出R字段和位置信息(每个引擎用来唯一标识数据行的信息,对于有主键的表这个rowid就是主键id,没有主键的就由系统生成一个rowid,对于memory引擎rowid就是数组的下标)放入sort_buffer中,按R字段排序。
4:排序完成后,取出limit10行返回给客户端。
tmp_table_size限制了内存临时表的大小,默认值是16M。如果临时表大小超过了这个值内存临时表就会转成磁盘临时表。
mysql5.6引入新排序算法,即优先队列排序算法,临时文件的算法是归并排序算法.
read_buffer_size和read_rnd_buffer_size:这两个都是按session独占的,增大read_rnd_buffer_size和max_length_for_sort_data可以改善orderbysql性能。
Max_length_for_sort_data大小决哪种(共两种)排序算法,超过此值会使用磁盘临时文件排序
Max_sort_length变量可以指定当用blob或text前缀排序时,这个前缀有多大
Sort_buffer_size默认是全局的,一旦排序mysql会立刻分配指定大小内存不管是否需要这么大,可以查询前增加,如下所示
set@@session.sort_buffer_size:=409600
#执行语句
Set@@session.sort_buffer_size:=default
MySQL支持两种方式的排序filesort和index,Usingindex是指MySQL扫描索引本身完成排序。index效率高,filesort效率低。
②orderby满足两种情况会使用Usingindex:
a.orderby语句使用索引最左前列。
b.使用where子句与orderby子句条件列组合满足索引最左前列。
③尽量在索引列上完成排序,遵循索引建立(索引创建的顺序)时的最佳左前缀原则。
④如果orderby的条件不在索引列上,就会产生Usingfilesort。
⑤groupby与orderby很类似,其实质是先排序后分组,遵照索引创建顺序的最佳左前缀原则。注意where高于having,能写在where中的限定条件就不要去having限定了。
usingFileSort优化有两种排序算法(摘自深入浅出mysql):
两次扫描算法:首先根据条件取出排序字段和行指针信息,之后在sourt_buffer中排序,如果sort_buffer不够,则在临时表temporarytable中存储排序结果,完成排序后,根据行指针回表读取记录。该算法是mysql4.1之前采用的算法。需要两次访问数据,第一次取排序字段和行指针(显示主键或是自动创建的隐式主键)信息,第二次根据行指针回表获取记录(可能会导致大量随机I/O操作),排序的时候内存开销小
一次扫描算法:一次性取出满足条件的行所有字段,然后在sourt_buffer中排序,真接输出结果集。排序时候内存开锁大,但是效率比两次排序算法要高。
mysql通过比较系统max_length_sort_data的大小和query语句取出字段的总大小来判断采用哪种算法。如果此值更大,则使用一次扫描排序算法,否则使用两次扫描排序算法。
Sortbuffer都是面向客户服务线程分配的,如果设置过大可能造成内存浪费。甚至导致内存交换。
回复

使用道具 举报

千问 | 2021-1-27 05:23:29 | 显示全部楼层
引用1楼jslqa67的回复:现在我的想法是创建一个100条数据的临时表,然后orderbyrand()limit3,觉得太繁琐
不需要建立临时表,直接使用一个已经存在的表(selectcount(*)>=3)就行
SELECTCEIL(RAND()*(100))fromtemp_tableorderbyrand()limit3;
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行