共计 1675 个字符,预计需要花费 5 分钟才能阅读完成。
最近写作生涯遭逢了滑铁卢,写了两篇文章浏览量都不怎么样,但还是要持续分享所学,服务端的菜鸡不能输,要从新称霸中原,233333 当然这是很难的,后端优良作者切实太多了,还得持续加油。回归主题,最近又在重新学习 MySQL,想起了阿里开发手册禁用 select * 查问语句,这是为什么呢
引言
阿里巴巴开发手册中指出:
【强制】在表查问中,一律不要应用 * 作为查问的字段列表,须要哪些字段必须明确写明
阐明:
- 减少查问分析器解析老本
- 增减字段容易与 resultMap 配置不统一
- 无用字段减少网络 耗费,尤其是 text 类型的字段
文章将从这几个方面开展阐明
减少查问分析器解析老本
首先介绍一下 MySQL 根本架构,根本构造如下图:
MySQL 根本架构能够分为 Server 层和存储引擎层两局部。Server 层包含连接器、查问缓存、分析器、优化器、执行器等。存储引擎层负责数据的存储和提取,其架构模式是插件式的,反对 InnoDB、MyISAM、Memory 等多个存储引擎
当咱们执行一条查问语句:select * from t where id = 1,在 MySQL 中执行过程如下:
- 在真正执行 select * from t where id = 1 时首先须要输出命令 mysql -uroot -p,通过连接器将客户端和服务层建设起连贯
- 建设起连贯当前输出 select * from t where id = 1 这条 SQL
- 首先查找查问缓存中是否曾经执行过该条语句
- 若未命中查问缓存,则执行 select * from t where id = 1 这条 SQL,分析器会对这条 SQL 进行词法剖析。
- MySQL 从输出的 select 这个关键字辨认进去这是一个查问语句。
- 把字符串 t 辨认成表名 t,把字符串 id 辨认成列 id
- 判断输出的这个 SQL 语句是否满足 MySQL 语法
如果应用 select 来查问语句,分析器须要 对进行额定的解析,如果间接指定成列名,则不须要进行额定的解析,间接辨认成列名
失去 MySQL 优化器“笼罩索引”策略优化的可能性
假如有一条 sql 语句为 select * from t where name = “ 何甜甜 ”,其中 id 为主键,name 为索引,而实际上这么写的目标只是想查问指定 name 的 id
在 innodb 存储引擎中,索引能够分为非主键索引和主键索引,主键索引和主键的区别在于叶子节点存放数据的不同。主键索引中叶子节点寄存的是整行数据,而非主键索引中叶子节点寄存的是主键的值。当初咱们来看 select * from t where name = “ 何甜甜 ” 这条语句是如何执行的
因为 name 是索引且 name 是查问条件,查问优化器会抉择应用 name 索引。首先依据 name 查问到该 name 对应的主键 id 为 1,因为须要查问的是指定 name 的所有数据,因而还须要依据主键 id 进行一次 回表 操作。所谓回表操作是指非主键索引中查问到主键 id,在依据主键 id 到主键索引中查问到所有数据,具体过程可看下图
后面曾经提到查问到的 中只是用到了 id 字段,如果将原来的 sql 语句批改为 select id from t where name = “ 何甜甜 ”,就能够防止一次回表操作。在非主键索引中曾经笼罩了查问需要【即所需查问的 ID 已在非主键索引上了】,也被称为 笼罩索引。通过笼罩索引能够缩小回表次数,从而显著晋升查问性能,因而在理论写 sql 过程中应该尽量避免写 select 这样的查问语句,写之前先反诘是否真的须要用到这么多字段
减少 IO 操作
BLOB 和 TEXT 是为了存储很大的数据而设计的字符串数据类型,当 BLOB 和 TEXT 值太大时,InnoDB 会应用专门的内部存储区域来进行存储,每个值在行内须要 1~4 字节存储一个指针,而后在内部存储区域存储理论的值,如果查问的 中有 BLOB 或 TEXT 类型的字段,则查问的 BLOB 或 TEXT 列须要在进行额定一次 IO 操作去内部存储区域将数据查问到,所以尽量避免应用 select
减少数据传输工夫和网络开销
传输数据过多会减少网络开销。同时,查问语句执行时会先将查问到的数据放到查问缓存区中,再从查问缓存中将后果返回给客户端,如果查问到的数据量十分大则须要花很多工夫来存储后果,所以在说一次,防止应用 select *