当前位置: 首页 > news >正文

mysql explain学习记录

参考了公司内相关博客,实践并记录下,为后面分析并优化索引做准备。

MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法,可以很好的分析SQL语句的执行情况。
每当遇到执行慢(在业务角度)的SQL,都可以使用explain检查SQL的执行情况,并根据explain的结果相应的去调优SQL等。

github链接: mysql explain学习

一、准备表

# 建表
CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;CREATE TABLE tmp (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;# 生成一些数据
# 定义存储过程
DROP PROCEDURE IF EXISTS proc_initData; 
DELIMITER $
CREATE PROCEDURE proc_initData()
BEGINDECLARE i INT DEFAULT 1;WHILE i<=10000 DOinsert into single_table(key1,key2,key3,key_part1,key_part2,key_part3,common_field) VALUES(substring(md5(rand()),1,15),floor(10000000 * rand()),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15),substring(md5(rand()),1,15));SET i = i+1;END WHILE;
END $
delimiter ;# 上面定义存储过程后,可能会有key冲突,可以多执行几次,生成较多测试数据
CALL proc_initData();

二、测试

mysql> EXPLAIN SELECT * FROM single_table\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: single_tablepartitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: NULL

对结果分析:

列名说明
id标识select所属的行。如果有子查询,会顺序编号
select_type显示本行是简单或复杂select
table表名
type针对单表的访问方法
possible_keys可能用到的索引
key实际用的索引
key_len实际使用索引里占用的字节数
ref当使用索引列为等值查询时,对应的匹配信息
rows预估需要读取的行数,估算值不精确
Extra额外信息

2.1 id

给SELECT语句分配的id,因为我们的SQL语句可能包括多个查询,比如有子查询,连表查询,像这样

mysql> EXPLAIN SELECT * FROM single_table WHERE key1 in (SELECT key1 FROM single_table where key2 > 'a')\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: single_tablepartitions: NULLtype: ALL
possible_keys: idx_key1key: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: Using where
*************************** 2. row ***************************id: 1select_type: SIMPLEtable: <subquery2>partitions: NULLtype: eq_ref
possible_keys: <auto_distinct_key>key: <auto_distinct_key>key_len: 303ref: sql_test.single_table.key1rows: 1filtered: 100.00Extra: NULL
*************************** 3. row ***************************id: 2select_type: MATERIALIZEDtable: single_tablepartitions: NULLtype: ALL
possible_keys: idx_key2,idx_key1key: NULLkey_len: NULLref: NULLrows: 6896filtered: 100.00Extra: Using where
3 rows in set, 2 warnings (0.41 sec)

为啥有三行?第一行和第二行都是1,第三行是2,这是为啥呢?跟接下来的select_type有点关系。

2.2 select_type

上面2.1的示例输出了三行,每行代表一个查询语句,select_type就是每行查询语句的类型,select_type的可选项比较多:

2.2.1、SIMPLE

查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型;连接查询也是这个类型

2.2.2、MATERIALIZED

上面示例的第三行就是这个类型,表明查询优化器把子查询物化成表了,第二行的table是就是这个物化表,前两行的id都是1,说明他们是连接查询,属于一个查询语句。

2.2.3、PRIMARY

对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY

EXPLAIN SELECT * FROM single_table UNION SELECT * FROM tmp;
2.2.4、UNION

对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNION

2.2.5、UINON RESULT

MySQL选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNION RESULT

2.2.6、其他

此外还有很多选项,有兴趣可以单独去了解。

3.3 partitions

忽略

2.4、type

查询一个数据,我们可以全表捞出来,然后再一条条对比找到这条数据,也可以通过索引马上得到它,这就是访问方式的不同,type就是表明使用了哪种访问方式,它也有很多选项,我们选其中一些来说:

2.4.1、const

当查询条件为主键或唯一键的等值匹配,就是这种类型,这种类型查询贼快。

EXPLAIN SELECT * FROM single_table where id=1;
2.4.2、eq_ref

在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的,被驱动表的查询方式就是这个

EXPLAIN SELECT * FROM single_table INNER JOIN tmp ON single_table.id = tmp.id;

2.4.3、ref

当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是ref

EXPLAIN SELECT * FROM single_table WHERE key1 = 'a';
2.4.4、index_merge

有些情况下会使用索引合并的查询,即使用多个索引进行查询,然后将结果合并

EXPLAIN SELECT * FROM single_table WHERE key1 = 'a' OR key3 = 'a';
2.4.5、range

使用索引字段的范围查询

EXPLAIN SELECT * FROM single_table WHERE key1 IN ('a', 'b', 'c');
2.4.6、index

有联合索引时,但是我们查询条件只包含联合索引的右边某个字段,造成没法走这个联合索引,需要全表扫描,index表明走该联合索引全表扫描而不是走聚簇索引全表扫描,为啥呢?
因为聚簇索引包含完整数据,二级索引只包含索引字段和主键列,更加轻量,全表扫描二级索引的成本更低。

EXPLAIN SELECT key_part2 FROM single_table WHERE key_part3 = 'a';
2.4.7、All

也就是全表扫描,危险信号!!!

2.5、possible_keys和key

possible_keys表示可能用到的索引,key表示实际使用索引。

EXPLAIN SELECT * FROM single_table WHERE key1 > 'z' AND key3 = 'a';

key1和key3都有索引,实际使用了key3的索引。MySQL会记录一些统计信息,查询优化器会判断使用哪个索引的成本更低就使用哪个索引。

2.6、key_len

实际使用索引的最大长度,单位字节。比如上面示例显示key_len是303个字节。咋算出来的呢?该字段是varchar(100),然后是utf8,utf8字符集是三个字节,
则是100*3=300,然后该字段可以为NULL,则需要一个字节作为标志位,并且因为是varchar类型,所以需要2个字节记录它的实际长度,所以是300+1+2=303.

2.7、ref

ref表明在通过索引进行等值比较时,跟索引比较的值的类型是什么。

EXPLAIN SELECT * FROM single_table WHERE key1 = 'a';

这里的key1=‘a’,'a’就是个常量,所以是const。还有其他类型就自行了解吧。

2.8、rows

如果是走索引,表示本次查询的扫描索引记录数;如果是全表扫描,表示全表记录数。看执行计划时,这个字段也是需要重点关注的。

2.9、Extra

额外的说明信息,种类比较多,只说几个吧,全面的文档在这:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

2.9.1、Using index

当我们的查询列和索引条件是同一个列,就是这个情况。啥意思呢?我们知道二级索引值存储了二级索引列和主键值,当查询列只包括二级索引列(或也有主键),则不需要回表查询聚簇索引了。
这也告诉我们,查询列尽量指明我们想要的列,如果查询条件是二级索引,查询列也是只有二级索引列(或也有主键),就能提升一定性能。

EXPLAIN SELECT key1 FROM single_table WHERE key1 = "2";
2.9.2、Using where

参考:https://segmentfault.com/q/1010000003094577

1、查询条件没有索引或索引字段被函数修饰造成索引失效,走全表扫描了;
2、有时会出现"Using where; Using index"或"Using index condition; Using where"的情况,意思就是通过索引查出了数据,然后再通过where条件过滤掉不符合条件的记录。
3、这个提示跟走没走索引没有关系,可以不用太纠结。知道它是用来过滤返回个客户端的数据的就行。

2.9.3、Using index condition

跟"Using index"一样,走索引了,但是涉及到的字段有些不在二级索引里,需要走一遍聚簇索引才能查到。

2.9.4、Impossible WHERE

where条件始终是false,不会命中任何记录,比如你的条件是“where 1 != 1"

2.9.5、Impossible WHERE noticed after reading const tables

1、用主键或唯一键查询时,查询一条不存在的记录。
2、关于"const"的解释:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html#jointype_const

三、索引失效的一些场景

1、通过二级索引查找时,还是查出了太多数据,这个时候如果需要回表去查聚簇索引就会有随机IO,造成性能低下,这样MySQL可能会直接走聚簇索引的全表扫描。
2、对索引字段用MySQL函数做了处理,比如我们对createTime建了索引,但是用的时候用date_format()包装了一下,也会使索引失效。
或者下列的情形:

SELECT * FROM single_table WHERE binary key1 = 'c90ab6cb630a35f';

3、模糊搜索时,使用了like “%xxx”的形式,因为MySQL的索引是左匹配的。
4、在使用联合索引时,必须带上最左边的字段(也是左匹配原则),比如a,b,c字段建立联合索引,则(a=x and b=x)和(a=x and c=x)都是走索引的,但是(b=x) (b=x and c=x)是不走索引的。
5、虽然是索引字段,但是使用了"not in"

EXPLAIN SELECT * FROM single_table WHERE key1 not in ("22");

6、使用"or"联系一个索引字段和一个非索引字段

EXPLAIN SELECT key1 FROM single_table WHERE key1 = 'a' or common_field = 'a';

索引失效的场景比较多,这里只归纳了部分:
index_dismiss.png

相关文章:

mysql explain学习记录

参考了公司内相关博客&#xff0c;实践并记录下&#xff0c;为后面分析并优化索引做准备。 MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法&#xff0c;可以很好的分析SQL语句的执行情况。 每当遇到执行慢&#xff08;在业务角度&#xff09;的SQL&#xff0c;…...

电压放大电路的作用有哪些(电压放大器)

电压放大电路是电子电路中常见且重要的组件&#xff0c;其主要作用是将输入信号的电压放大到所需的输出电压级别&#xff0c;并保持输入信号的形状和准确度。电压放大电路广泛应用于各种电子设备和系统中&#xff0c;具有以下几个重要的作用&#xff1a; 信号放大&#xff1a;电…...

编译opencv-3.4.5 [交叉编译]

在unbuntu20.04环境下编译opencv3.4.5&#xff0c; cmake 版本&#xff1a;3.27.4 gcc 版本&#xff1a;11.4.0 g版本&#xff1a;11.4.0 在此环境下编译opencv4.5.4正常。 1. 编译时遇到的问题 &#xff08;1&#xff09; Built target libprotobuf make: *** [Makefile:163…...

Canal 实现MySQL与Elasticsearch7数据同步

1 工作原理 canal 模拟 MySQL slave 的交互协议&#xff0c;伪装自己为 MySQL slave &#xff0c;向 MySQL master 发送 dump协议 MySQL master 收到 dump 请求&#xff0c;开始推送 binary log 给 slave (即 canal ) canal 解析 binary log 对象(原始为 byte 流) 优点&…...

网络安全攻防对抗之隐藏通信隧道技术整理

完成内网信息收集工作后&#xff0c;渗透测试人员需要判断流量是否出得去、进得来。隐藏通信隧道技术常用于在访问受限的网络环境中追踪数据流向和在非受信任的网络中实现安全的数据传输。 一、隐藏通信隧道基础知识 &#xff08;一&#xff09;隐藏通信隧道概述 一般的网络通…...

读书笔记:多Transformer的双向编码器表示法(Bert)-2

多Transformer的双向编码器表示法 Bidirectional Encoder Representations from Transformers&#xff0c;即Bert&#xff1b; 第2章 了解Bert模型&#xff08;掩码语言模型构建和下句预测&#xff09; 文本嵌入模型Bert&#xff0c;在许多自然语言处理任务上表现优秀&#…...

Python 基于PyCharm断点调试

视频版教程 Python3零基础7天入门实战视频教程 PyCharm Debug&#xff08;断点调试&#xff09;可以帮助开发者在代码运行时进行实时的调试和错误排查&#xff0c;提高代码开发效率和代码质量。 准备一段代码 def add(num1, num2):return num1 num2if __name__ __main__:f…...

spring security auth2.0实现

OAuth 2.0 的认证/授权流程 jwt只是认证中的一步 4中角色 资源拥有者&#xff08;resource owner&#xff09;、客户端&#xff08;client 第三方&#xff09;、授权服务器&#xff08;authorization server&#xff09;和资源服务器&#xff08;resource server&#xff09;。…...

MySQL(6)LOCK和MVCC

一、锁的分类 按照锁的属性&#xff1a;读锁、写锁、共享锁、排它锁、悲观锁、乐观锁 按照锁的范围&#xff1a;表锁、页锁、间隙锁、临键锁、行锁 按照锁的作用&#xff1a;意向锁、意向共享锁、意向排它锁、IS锁、IX锁 二、MySQL为什么要有锁 锁是计算机协调多个进程或线程并…...

最新IDE流行度最新排名(每月更新)

2023年09月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&#xff0c;Top IDE索引可以帮助您决定在软件开发项目中使用哪个IDE …...

I2C的上拉电阻如何计算?

说明&#xff1a; 1、本文只说明I2C上拉电阻的最小值如何计算。 2、I2C最小值和最大值计算的详细原理可以参考这篇文章&#xff1a;https://mp.weixin.qq.com/s/ZvJJ0rPRd_STULj8g1H81A。 3、I2C最小值的计算方式比较简单&#xff0c;在实际应用中计算出最小值&#xff0c;然后…...

Centos下安装 oracle11g 博客2

[oraclewangmengyuan database]$ ./runInstaller -silent -responseFile /home/oracle/database/response/db_install.rsp -ignorePrereq ./runInstaller -silent -responseFile /home/oracle/database/response/db_install.rsp -ignorePrereq 正在启动 Oracle Universal Insta…...

记一次逆向某医院挂号软件的经历

背景 最近家里娃需要挂专家号的儿保&#xff0c;奈何专家号实在过于抢手&#xff0c;身为程序员的我也没有其他的社会资源渠道可以去弄个号&#xff0c;只能发挥自己的技术力量来解决这个问题了。 出师不利 首先把应用安装到我已经 Root 过的 Pixel 3 上面&#xff0c;点击应…...

Canal实现Mysql数据同步至Redis、Elasticsearch

文章目录 1.Canal简介1.1 MySQL主备复制原理1.2 canal工作原理 2.开启MySQL Binlog3.安装Canal3.1 下载Canal3.2 修改配置文件3.3 启动和关闭 4.SpringCloud集成Canal4.1 Canal数据结构![在这里插入图片描述](https://img-blog.csdnimg.cn/c64b40c2231a4ea39a95aac81d771bd1.pn…...

Kafka的消息传递保证和一致性

前言 通过前面的文章&#xff0c;相信大家对Kafka有了一定的了解了&#xff0c;那接下来问题就来了&#xff0c;Kafka既然作为一个分布式的消息队列系统&#xff0c;那它会不会出现消息丢失或者重复消费的情况呢&#xff1f;今天咱们就来一探。 实现机制 Kafka采用了一系列机…...

Docker 部署 Firefly III 服务

拉取最新版本的 Firefly III 镜像&#xff1a; $ sudo docker pull fireflyiii/core:latest在本地预先创建好 upload 和 export 目录, 用于映射 Firefly III 容器内的 /var/www/html/storage/upload 和 /var/www/html/storage/export 目录。 使用以下命令来运行 Firefly III …...

配置OSPFv3基本功能 华为笔记

1.1 实验介绍 1.1.1 关于本实验 OSPF协议是为IP协议提供路由功能的路由协议。OSPFv2&#xff08;OSPF版本2&#xff09;是支持IPv4的路由协议&#xff0c;为了让OSPF协议支持IPv6&#xff0c;技术人员开发了OSPFv3&#xff08;OSPF版本3&#xff09;。 无论是OSPFv2还是OSPFv…...

【AI视野·今日Sound 声学论文速览 第九期】Thu, 21 Sep 2023

AI视野今日CS.Sound 声学论文速览 Thu, 21 Sep 2023 Totally 1 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;Auto-ACD,大规模文本-音频数据集自动生成方法。 基于现有的大模型和api构建了一套大规模高质量的音频文本数据收集方法&#xff0c…...

数据结构-----堆(完全二叉树)

目录 前言 一.堆 1.堆的概念 2.堆的存储方式 二.堆的操作方法 1.堆的结构体表示 2.数字交换接口函数 3.向上调整&#xff08;难点&#xff09; 4.向下调整&#xff08;难点&#xff09; 5.创建堆 6.堆的插入 7.判断空 8.堆的删除 9.获取堆的根(顶)元素 10.堆的遍历…...

set/multiset容器、map容器

目录 set/multiset容器 set基本概念 set大小和交换 set插入和删除 查找和统计 set和multiset的区别 改变set排序规则 set存放内置数据类型 set存放自定义数据类型 pair队组 map容器 map容器的基本概念 map构造和赋值 map大小和交换 map插入和删除 map查找和统计…...

Linux系统编程——总结初识Linux(常用命令、特点、常见操作系统)

文章目录 UNIX操作系统&#xff08;了解&#xff09;Linux操作系统主要特征Linux和unix的区别和联系什么是操作系统常见的操作系统Ubuntu操作系统Ubuntu安装linux下的目录的类型(掌握)shell指令shell指令的格式文件操作相关指令系统相关命令网络相关命令其他命令软件安装相关的…...

Js使用ffmpeg进行视频剪辑和画面截取

ffmpeg 使用场景是需要在web端进行视频的裁剪&#xff0c;包括使用 在线视频url 或 本地视频文件 的裁剪&#xff0c;以及对视频内容的截取等功能。 前端进行视频操作可能会导致性能下降&#xff0c;最好通过后端使用java&#xff0c;c进行处理&#xff0c;本文的案例是备选方…...

Linux基本命令,基础知识

进到当前用户目录&#xff1a;cd ~ 回到上级目录:cd .. 查看当前目录层级:pwd 创建目录:mkdir mkdir ruanjian4/linux/zqm41 -p级联创建文件夹(同时创建多个文件夹需要加-p) 查看详细信息:ls -l (即 ll) 查看所有详细信息:ls -al 隐藏文件是以.开头的 查看&#xff1a;l…...

【Android知识笔记】进程通信(三)

在上一篇探索Binder通信原理时,提到了内存映射的概念,其核心是通过mmap函数,将一块 Linux 内核缓存区映射到一块物理内存(匿名文件),这块物理内存其实是作为Binder开辟的数据接收缓存区。这里有两个概念,需要理解清楚,那就是操作系统中的虚拟内存和物理内存,理解了这两…...

云上亚运:所使用的高新技术,你知道吗?

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 前言 一.什么是云上亚运会 二.为什么要使用云…...

数据结构简述,时间、空间复杂度,学习网站推荐

目录 IT 学习路线 相关坚韧大厚书 相关有趣/耐看书或视频 数据结构与算法学习网站推荐 刷题 时间、空间复杂度 数据结构简述 基本概念 数据结构与算法简述和CS综述整理。本文非基础的教程&#xff0c;本文会列出大量学习和参考网站。老惯例&#xff0c;一个文章是一个集…...

在线安装qt5.15之后任意版本

下载qt现在安装包&#xff1a; window安装包链接 进入cmd&#xff0c;用命令行打开安装包&#xff0c;并指定组件下载地址&#xff08;这个是关键&#xff0c;之前用的是腾讯镜像&#xff0c;出现了版本灰色无法选中问题&#xff09; .\qt-unified-windows-x64-4.6.1-online…...

【kafka实战】01 3分钟在Linux上安装kafka

本节采用docker安装Kafka。采用的是bitnami的镜像。Bitnami是一个提供各种流行应用的Docker镜像和软件包的公司。采用docker的方式3分钟就可以把我们想安装的程序运行起来&#xff0c;不得不说真的很方便啊&#xff0c;好了&#xff0c;开搞。使用前提&#xff1a;Linux虚拟机&…...

yum安装mysql8

记录一下安装过程用于后面项目参考 目录 说明安装步骤yum安装默认目录修改默认的数据目录必要的my.cnf属性修改卸载Mysql 说明 一般情况下都是docker安装&#xff0c;部分特殊情况下&#xff0c;例如老外的项目部分禁用docker&#xff0c;那一般二进制安装或者yum直接安装。 …...

十五)Stable Diffusion使用教程:另一个线稿出3D例子

案例:黄金首饰出图 1)线稿,可以进行色阶加深,不易丢失细节; 2)文生图,精确材质、光泽、工艺(抛光、拉丝等)、形状(包括深度等,比如镂空)和渲染方式(3D、素描、线稿等)提示词,负面提示词; 3)seed调-1,让ai随机出图; 4)开启controlnet,上传线稿图,选择cann…...

网站备案最多需要多久/长春网站关键词排名

1 Opencv&#xff1a;1.1 OpenCV是计算机视觉领域应用最广泛的开源工具包&#xff0c;基于C/C&#xff0c;跨平台的。1.2 OpenCV最早源于Intel公司1998年的一个研究项目。1.3 OpenCV旨在提供一个用于计算机视觉的科研和商业应用的高性能通用库。1.4 并提供了Python&#xff0c;…...

泰安直聘网官网/seo搜索引擎优化排名

工厂模式之观察者模式...

东莞网站建设-信科网络/鞋子软文推广300字

导读&#xff1a; "虚拟导游空气中讲解"有望亮相世博会 [来 源] 新闻晚报 [发表时间] 2007-9-12 [浏览次数] 290 展会上&#xff0c;一个和真人一样大小的虚拟导游在为游客讲解&#xff0c;“他”的影像浮现在空气中&#xff0c;不需要在屏幕上成像……这…...

做网站是否过时了/怎样设计一个网页

网上看到很多移动端适配的各种方法&#xff0c;由于原来工作中对rem的疏忽&#xff0c;所以决定重新学习rem~ 由于移动端特殊性&#xff0c;本文讲的是如何使用rem实现自适应&#xff0c;或叫rem响应式布局&#xff0c;通过使用一个脚本就可以rem自适应&#xff0c;不用再为各种…...

公司找人做网站/东莞网站优化

scrapy框架 &#xff08;使用之前如果没有相应的模块需要安装&#xff0c;然后import scrapy&#xff09; scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架&#xff0c;可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程序中。…...

网站互动营销/深圳互联网公司排行榜

做开发我喜欢阅读开发文档&#xff0c;我觉得开发文档不仅仅是教你开发的步骤&#xff0c;教你如何调用接口。我们要学的还有那里面的业务逻辑处理&#xff0c;安全防范&#xff0c;开发文档作为公开的文档&#xff0c;那么多人使用别人的代码是经得起考验的&#xff0c;多看看…...