MySQL深入——9

如何正确的显示随机信息?

我们来模拟在英语单词app当中随机出现三个英语单词的情况,我们首先创建一张表words,然后给这个表当中插入10000条信息进行量化。

sql 复制代码
select word from words order by rand() limit 3;

order by rand()就是随机取三个的意思,接着我们使用Explain语句来看看这个命令,发现他要进行排列而且要创建临时表,对于优化器来说,是处理的行数越少越好,就使用了rowid排序进行,rowid排序(https://blog.csdn.net/Cobrander2_0/article/details/134861949https://blog.csdn.net/Cobrander2_0/article/details/134861949)就是先创建一张临时表出来,从words表当中按照主键顺序取出主键,然后使用rand()对每一个主键进行操作得到他们特有的数字存入到临时表当中,现在这个临时表当中存在10000条数据了,然后初始化sort_buffer,将这个数字和主键存入,这个过程当中遍历了一遍临时表扫描行数变成20000,接着在sort_buffer当中对数字进行排序,然后输出前三个,扫描行数变成了20003。

在这个过程当中生成了临时表,并且表排序的时候使用了rowid方法。

那么是不是所有的临时表都是内存表?其实不然,tmp_table_size限制了内存临时表的大小,当超过他的大小限制的时候,就会转化为磁盘临时表,当变为磁盘临时表的时候,执行上面的语句,也会变得不一样,我们会发现它使用的临时文件变为0了,这是因为他并没有使用并归排序算法,而是优先队列排序算法。

优先队列排序

我们现在的SQL语句是需要三个值的,但是我们对全表都进行了排序,这浪费了很多的计算量,而优先队列算法可以精确的只得到三个值,简单的来说就是使用了堆,取出10000行的前三行构成一个堆,然后取出下一行与这个堆里面的最大值进行比较,如果下一行的值小于这个堆里面的最大值,就对他进行替换,接着重复这一步直到结尾。

但是为什么我们上面的语句并没有使用到优先队列排序呢?这是因为使用这个算法的话,对堆维护的大小就是10000行的(name,rowid),超出了设置的sort_buffer_size值,所以只能使用rowid算法。

总之不管使用什么类型的临时表,order by rand()这个写法都耗费了巨大的资源。

那么有没有什么方法可以让耗费的资源变小呢???

随机排序方法

sql 复制代码
mysql> select count(*) into @C from t;
set @Y = floor(@C * rand());
set @sql = concat("select * from t limit ", @Y, ",1");
prepare stmt from @sql;
execute stmt;
DEALLOCATE prepare stmt;

我们首先使用count*来将这个表当中的行数C确定下来,接着使用floor和rand()方法取出来一个随机的0~C的整数Y,然后使用concat(是一个字符串连接函数,用于将多个字符串合并成一个字符串)将Y行当中的信息取出并输出,这个句子的意思是构建一个SQL查询,该查询从表 t 中选取一定数量的行。@Y 变量决定了从哪一行开始选取。

MySQL处理limit Y,1 的做法就是按顺序一个一个地读出来,丢掉前Y个,然后把下一个记录作为返回结果,因此这一步需要扫描Y+1行。再加上,第一步扫描的C行,总共需要扫描C+Y+1行。这个代价是要小于前面的order by rand()语句的。

prepare stmt from @sql;

这段代码的目的是从 @sql 变量中获取SQL查询字符串,并准备一个预处理语句。预处理语句是一种优化的方式,用于执行相同的SQL查询多次,而不需要每次都重新解析和编译查询。这样可以提高执行效率。

在准备好预处理语句后,可以使用 execute stmt 命令来执行它。执行完毕后,使用 deallocate prepare stmt 命令来释放预处理语句。

如果要输出三个单词,就找到三个Y值,然后在表当中取出这个Y行,接着使用concat进行拼接后输出。

相关推荐
bksczm9 分钟前
InnoDB 页结构详解:页类型、页头页尾、数据行与页目录
数据库·mysql
bksczm1 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
余槐i1 小时前
MySQL 8.0 联合索引走错:为什么加了索引查询反而从 200ms 变成 8s
java·spring boot·mysql·docker·性能优化
字节跳动开源1 小时前
OpenViking连接业务系统,LLM Wiki一键编译
数据库·开源
进击的荆棘2 小时前
MySQL——数据库基础
数据库·mysql
Decay__2 小时前
22_MySQL 运维自动化平台 —— 部署编排 + 监控 + 巡检 + 告警 + 工单闭环一体化
运维·数据库·sql·mysql·架构
FungLeo3 小时前
成为全栈·基础补充·数据库索引:为什么加了索引还是慢
mysql·postgresql·sqlite·sql优化·数据库索引·成为全栈
codeejun3 小时前
每日一Go·MySQL-11、覆盖索引 & 回表原理
javascript·数据库·mysql
CoderYanger3 小时前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)
java·数据库·spring·面试·职场和发展·java-ee·mybatis
XLYcmy4 小时前
信息检索报告数字经济赋能城市低碳治理的路径研究——基于“传统数据库 + 生成式人工智能”双轮驱动的检索实践 检索实施与结果分析 Web of Science
数据库·ai·llm·prompt·ssci·deepseek·wos