『MySQL 实战 45 讲』17 - 如何正确地显示随机消息?(随机抽取 3 个词)

news2024/11/22 16:27:12

如何正确地显示随机消息?(随机抽取 3 个词)

  1. 需求:从用户的英语单词表中,随机选择三个单词,创表和插入数据如下:
# 建表
CREATE TABLE `words` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `word` VARCHAR(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB;
# 插入数据
DELIMITER ;;
CREATE PROCEDURE idata()
BEGIN
  DECLARE i INT;
  SET i=0;
  WHILE i<10000 DO
    INSERT INTO words(word) VALUES(CONCAT(CHAR(97+(i DIV 1000)), CHAR(97+(i % 1000 DIV 100)), CHAR(97+(i % 100 DIV 10)), CHAR(97+(i % 10))));
    SET i=i+1;
  END WHILE;
END;;
DELIMITER ;

CALL idata();

内存临时表

  1. 实现的逻辑可以这样
# 每行随机一个数字之后,排序
select word from words order by rand() limit 3;
  1. 通过 explain 查看语句的执行情况
  • Using temporary:表示用了临时表,临时表分内存临时表和磁盘临时表,看实际数据量才知道有没有变为磁盘临时表
  • Using filesort:表示的是需要执行排序操作
    在这里插入图片描述
  1. 对于内存临时表(使用 Memory 引擎,这时候的数据量能够存在内存临时表下,tmp_table_size 默认 16M,超过了才会转为磁盘临时表),回表过程只是简单地根据数据行的位置,直接访问内存得到数据,根本不会导致多访问磁盘,MySQL 就会选择 rowid 排序
    在这里插入图片描述
  • 创建一个临时表。这个临时表使用的是 memory 引擎,表里有两个字段,第一个字段是 double 类型,记为字段 R,第二个字段是 varchar(64) 类型,记为字段 W。并且,这个表没有建索引
  • 从 words 表中,按主键顺序取出所有的 word 值。对于每一个 word 值,调用 rand() 函数生成一个大于 0 小于 1 的随机小数,并把这个随机小数和 word 分别存入临时表的 R 和 W 字段中,到此,扫描行数是 10000
  • 现在临时表有 10000 行数据了,接下来在这个没有索引的内存临时表上,按照字段 R 排序
  • 初始化 sort_buffer。sort_buffer 中有两个字段,一个是 double 类型,另一个是整型
  • 从内存临时表中一行一行地取出 R 值和 pos 位置信息(MEMORY 引擎不是索引组织表,这个 pos 即 rowid,其实是数组下标)
  • 分别存入 sort_buffer 中的两个字段里。这个过程要对内存临时表做全表扫描,此时扫描行数增加 10000,变成了 20000
  • 在 sort_buffer 中根据 R 的值进行排序。注意,这个过程没有涉及到表操作,所以不会增加扫描行数
  • 排序完成后,取出前三个结果的位置信息,依次到内存临时表中取出 word 值,返回给客户端。这个过程中,访问了表的三行数据,总扫描行数变成了 20003
  1. 使用 slow.log 验证扫描到的行数
# 查看慢日志存储位置
show variables like '%slow%'; 
# 开启慢查询
set global slow_query_log=ON;
# 记录了包含所有执行时间超过参数 long_query_time 的 sql
set long_query_time=0;

select word from words order by rand() limit 3;

在这里插入图片描述
5. 小结:order by rand() 使用了内存临时表,内存临时表排序的时候使用了 rowid 排序方法

磁盘临时表

  1. tmp_table_size 限制了内存临时表的大小,默认值是 16M。如果临时表大小超过了 tmp_table_size,那么内存临时表就会转成磁盘临时表
  2. 磁盘临时表默认为 InnoDB 存储引擎,由 internal_tmp_disk_storage_engine 控制
  3. 复现场景,使用下面的参数
set tmp_table_size=1024;
set sort_buffer_size=32768;
set max_length_for_sort_data=16;
/* 打开 optimizer_trace,只对本线程有效 */
SET optimizer_trace='enabled=on'; 

/* 执行语句 */
select word from words order by rand() limit 3;

/* 查看 OPTIMIZER_TRACE 输出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

在这里插入图片描述
4. 分析

  • 这里的 sort_mode 现实 rowid 排序
  • num_examined_rows 总行数 1w,R 字段 8 字节,rowid 字段 6 字节,合计 14w 字节,应该超过 sort_buffer_size 的 32768 字节,但是 num_initial_chunks_spilled_to_disk 却为 0?
  1. 原因
  • 使用了优先队列排序算法,其实只要取 R 的最小的 3 个 rowid
    在这里插入图片描述

  • 对于这 10000 个准备排序的 (R,rowid),先取前三行,构造成一个堆

  • 取下一个行 (R’,rowid’),跟当前堆里面最大的 R 比较,如果 R’小于 R,把这个 (R,rowid) 从堆中去掉,换成 (R’,rowid’)

  • 重复第 2 步,直到第 10000 个 (R’,rowid’) 完成比较

随机排序选择方法

  1. 方案一
  • 假设随机选择 1 个值,后面重复 3 次
  • 取得这个表的主键 id 的最大值 M 和最小值 N
  • 用随机函数生成一个最大值到最小值之间的数 X = (M-N)*rand() + N
  • 取不小于 X 的第一个 ID 的行
SELECT MAX(id),MIN(id) INTO @M,@N FROM t ;
SET @X= FLOOR((@M-@N+1)*RAND() + @N);
SELECT * FROM t WHERE id >= @X LIMIT 1;

在这里插入图片描述

  • 缺点
    • 对于 id 数据不均匀,例如 1、2、40000、40001,那么取到 40000 的几率就很大
  1. 方案二
  • 取得整个表的行数,并记为 C
  • 取得 Y = floor(C * rand())。 floor 函数在这里的作用,就是取整数部分
  • 再用 limit Y,1 取得一行
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;

在这里插入图片描述

  • 缺点
    • 虽然解决了方案一的问题,但是 MySQL 处理 limit Y,1 的做法就是按顺序一个一个地读出来,丢掉前 Y 个,然后把下一个记录作为返回结果,因此这一步需要扫描 Y+1 行。再加上,第一步扫描的 C 行,总共需要扫描 C+Y+1 行,执行代价比随机算法一的代价要高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/565996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Chatgpt版本的opencv安装教程

文章目录 前言一、安装opencv方法一二、安装opencv方法二 前言 最近刚买了台RTX 3070的电脑&#xff0c;顺手刷了个ubuntu系统专门玩Carla&#xff0c;为了方便查资料&#xff0c;也顺手搭了浏览chatgpt的环境&#xff0c;用的clash&#xff0c;还挺好用的。然后刚好在看Carla…

(转载)MATLAB智能算法30个案例分析(4)——基于遗传算法的TSP算法

1 理论基础 TSP(traveling salesman problem,旅行商问题)是典型的NP完全问题&#xff0c;即其最坏情况下的时间复杂度随着问题规模的增大按指数方式增长&#xff0c;到目前为止还未找到一个多项式时间的有效算法。 TSP问题可描述为&#xff1a;已知n个城市相互之间的距离&…

chatgpt赋能python:PythonUrwid:一个优秀的控制台UI工具

Python Urwid&#xff1a;一个优秀的控制台UI工具 在开发控制台应用程序时&#xff0c;通常需要一种轻而易举的方法来创建用户界面。Python Urwid是一个高效&#xff0c;可定制的控制台UI工具&#xff0c;它可以帮助你创建强大的用户界面&#xff0c;同时获取出色的响应时间。…

SpringCloudAlibaba:继解决登录问题之后,Sentinel持久化没有效果问题

说实话好麻烦&#xff0c;每次使用关于Nacos的时候&#xff0c;bootstrap.yaml中都得配置username和password。 我后悔了。。。 哪位大哥有好办法啊&#xff01;&#xff01;&#xff01; 因为之前开启登录鉴权&#xff0c;导致使用Nacos就得配username和password&#xff0c…

day2 - 使用OpenCV进行图像的读取与展示

本期将使用OpenCV对图像进行一些基本的了解和操作&#xff1a;主要包含图像的读取、展示和保存&#xff0c;以及查看图像的基本属性&#xff0c;让我们充分的了解图像&#xff0c;为后续图像处理做准备。 完成本期内容&#xff0c;你可以&#xff1a; 会使用OpenCV对图像进行读…

Redis常用命令详解

Redis 是Remote Dictionary Service 的简称&#xff1b;也是远程字典服务。它是内存数据库&#xff0c;KV 数据库&#xff0c;数据结构数据库。它是一个单线程的单reactor模型。其交互方式是请求响应方式。在正常情况下&#xff0c;如果向redis发出请求&#xff0c;则一定会有响…

MyBatis 框架

MyBatis 框架 MyBatis 简介搭建 MyBatis 开发环境核心配置文件详解mapper 映射文件&#xff08;实现增删改查&#xff09;MyBatis获取参数值的两种方式MyBatis的各种查询功能特殊SQL的执行自定义映射resultMapresultMap 字段和属性的映射多对一映射处理一对多映射处理 动态SQLM…

11 - YOLO算法二 (目标检测)

要点&#xff1a; 三 YOLO v3 3.1 Darknet-53 &#xff08;backbone&#xff09; 3.2 目标边界框的预测 将预测的边界框中心限制在当前cell中&#xff0c; s(x) Sigmoid(x) 。 3.3 正负样本的匹配 3.4 损失的计算 3.4.1 置信度损失 (Binary Cross Entropy) 其中 表示预测…

能耗监测系统在淼泉卫生院项目的应用

摘要&#xff1a;随着社会生活水平的提高&#xff0c;经济的繁荣发展&#xff0c;人们对能源的需求逐渐增长&#xff0c;由此带来的能源危机日益严重。办公建筑、医院、商场等场所如何实时的了解、分析和控制能源消耗已成为需要解决的迫在眉睫的难题。传统的能源消耗只能以月/季…

CPU性能优化:分支预测

条件跳转引起的控制冒险虽然也可以通过在流水线中插入空泡来避免&#xff0c;但是当流水线很深时&#xff0c;需要插入更多的空泡。一个20级的流水线为例&#xff0c;如果一条指令需要上一条指令的执行结束才能执行&#xff0c;则需要在这两条指令之间插入19个空泡&#xff0c;…

STL详解— list类的模拟实现

本文章所需实现三个类及其每个类里的各个函数接口总览&#xff1a; namespace zhc {//模拟实现list当中的结点类template<class T>struct list_node{//成员函数list_node(const T& val T()); //构造函数//成员变量T _val; //数据域list_node<T&g…

推荐系统简介

文章目录 推荐系统的分类基于人口统计学的推荐算法基于内容的推荐算法基于协同过滤的推荐算法协同过滤&#xff08;CF&#xff09;推荐方法基于近邻基于用户的协同过滤基于物品的协同过滤 混合推荐推荐系统实验方法离线实验用户调查在线实验 学习下b站上尚硅谷的推荐系统的课程…

易观千帆 | 2023年4月证券APP月活跃用户规模盘点

易观&#xff1a;2023年4月证券服务应用活跃人数13924.88万人&#xff0c;相较上月&#xff0c;环比下降1.46%&#xff0c;同比增长3.64%&#xff1b;2023年4月自营类证券服务应用Top10 活跃人数6144.02万人&#xff0c;环比下降0.01%&#xff1b;2023年4月第三方证券服务应用T…

「远程开发」VSCode使用SSH远程linux服务器 - 公网远程连接(1)

文章目录 前言视频教程1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 转…

chatgpt赋能python:PythonWorkon-使Python多环境管理更加轻松

Python Workon - 使Python多环境管理更加轻松 Python是一种广泛使用的高级编程语言&#xff0c;在众多开发者中应用广泛。在实际工作中&#xff0c;我们有时需要使用不同版本的Python或不同的环境来开发不同的项目。这时候就需要一个Python环境管理器来帮助我们快速地进行环境…

chatgpt赋能python:PythonWSDL:实现更好的Web服务和集成

Python WSDL&#xff1a;实现更好的Web服务和集成 在现代的互联网世界中&#xff0c;我们面临着不断增长的需求&#xff0c;需要实现与不同系统之间的交互和数据共享。Web服务是一种解决方案&#xff0c;允许应用程序通过互联网相互通信。其中Web服务描述语言&#xff08;WSDL…

python+django在线音乐分享网站系统vue_6045i.

本系统主要包括管理员和用户&#xff1a;主要包括个人中心、用户管理、通知公告管理、音乐类型管理、音乐分享管理、音乐榜单管理、音乐论坛、系统管理等功能的管理系统。 (1)绪论 系统的开发背景&#xff0c;意义和系统状况等&#xff0c;详细讲述了系统的用处&#xff0c;对本…

iOS App外包开发解决闪退问题

在iOS应用开发中&#xff0c;闪退&#xff08;应用程序意外退出&#xff09;是一个常见的问题。为了查找和解决闪退问题&#xff0c;可以使用以下工具和方法。今天和大家分享这方面的知识&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开…

扬州晶澳-年产3GW高性能太阳能光伏组件项目Acrel-3000WEB电能管理系统的设计及应用

摘要&#xff1a;在信息时代&#xff0c;电力信息系统的应用促迚了电力企业的収展&#xff0c;增强了电力系统运行的安全性与稳定性&#xff0c;对满足用户需求其有重要意义。随着国家电网改革政策的逐步推进和落实&#xff0c;Acrel-3000WEB电能管理系统运用互联网和大数据技术…

数据库索引结构(4)---基于B+树的查询

回顾我们学习的线性和课扩展哈希 他们都只能进行等值操作 但是不能进行区间操作 为了进行区间操作和关系的比较和速度考虑 引入数据结构B树 序言:磁盘存储 1. mysql面试题-深入理解B树原理_哔哩哔哩_bilibili 信息是存取在磁盘块中的每个 磁盘最小的存取单位是512KB 要定位磁…