作者:小指标青年\
起源:https://blog.csdn.net/qq_3538...

前言

不倡议应用 select *

这几个字眼,做开发的都不生疏吧。

阿里的开发手册下面也是有提到:

这个完整版能够关注公众号Java核心技术,而后在公众号后盾回复手册获取。

昨晚收到一个小兄弟的反馈:

随后也问了下学习群里的兄弟们,

不敢吱声的:

如同派:

离谱的:

那么,我作为一个出手侠, 我必然要出手了。

出手侠:

习惯用语,等到xxxxx的时候,我就会出手。

注释

这个完整版能够关注公众号Java核心技术,而后在公众号后盾回复手册获取。其实阿里巴巴手册上阐明的三点了:

1) 减少查问分析器解析老本

什么是分析器老本,什么货色,我顺手画个简图,大家晓得一下:

就是这个分析器,这里会去解析你的sql的语法,词法。

举例,如果是select * from user , 看到 * ,就会去看看是哪个表 user,而后 Query Table Metadata For Columns,把所有列值给你支楞进去,填充成相似 select id ,name ,age,phone form user 这样子。(当然还有其余剖析了,例如如语法的判断, 字段的判断, 表名等等)

说实话。这个分析器的老本....你要是说减少了解析老本,我的确能了解。

然而我感觉老本也不是很大.... 除非是个大表,大到查问完所有列值?

so,我能承受,然而承受得不多。

2) 增减字段,容易与resultMap 配置不统一

这一点我不想说。说切实的,有时候写select *(须要查表所有列值的时候), 我实体加了字段,我改了resultMap ,我sql还不必动。

这一点属于是平时应用标准上的躲避点了,不多言。

3)无用字段减少网络耗费、磁盘IO开销

这一点有考究。

能够看到我第一点外面画的简图, 如果说

不思考缓存 存在的时候:

最终会走到执行器,而后执行器前面其实是引擎层

引擎层这里我就不开展了,引擎层外面其实包含了各种日志(undo、redo、binlog等)的记录,还有就是在内存里找数据。

简略点演绎,其实这种查问操作就是刷盘操作,从磁盘刷入内存,波及到的 磁盘IO开销。

那么在刷盘操作的时候,是不是真的selec * 就真的会 减少 磁盘IO开销呢?

答案,必定是的。然而 增大的影响水平,我必须说一下:

如果你说 ,表外面就三字段 , id ,name ,age ,原本查 id ,name ;因为 select * ,变成查多了一个 age , 增大磁盘IO开销 ?

我感觉是增大了,然而简直不必理。因为这些都是失常的数据类型,开销增大不了多少。

所以,真正暗藏的雷是什么?

有大字段

例如

tinytext、text、mediumtext、longtexttinybob、blob、mediumblob、longblob

这些家伙,在mysql上,就是当做一个独立的对象解决。

这时候就真的要审慎了。

如果你是个比拟多字段的表,例如什么意见反馈表,留言不确定长度,用了text ,还有回复留言字段也用了text ;

又例如博客文本表,为了存content,用了这些大字段。

原本想查问一下 意见的反馈人名 ,或者是 查问博客的题目,后果因为懒或者不留神,写了select *., 查问的时候带进去这些 大字段。

那么显然,这时候读取的内容数据就是真的比原先初衷要大很多(没准业主小丹投诉保安,意见反馈的留言给你写了篇小论文), 这时候因为读取的内容多,磁盘IO开销多,而后返回数据包给客户端量也多, 这样 就真的是有影响了。

4) 补充,其实也是我首当其冲想说的一点

无奈应用索引笼罩

ps:明天学习成语了吗?不要乱用成语。

select * 根本辞别索引笼罩了

什么是索引笼罩?

举例 :

给name字段 建索引, 查问的时候,只用到了 索引的字段,这就是索引笼罩 。

也就是间接通过查问索引,拿进去的数据就曾经满足了查问返回的字段数据。无需额定其余查问操作了,也就是索引笼罩了。这样必定快。

如果初衷是查 name, 后果写成了 select * , 变成查多了其余字段, 那其余字段不是索引,必定无奈触发索引笼罩应用场景了,也就是须要额定的回表查问操作了,那这样就慢了。

回归正题,因为写成select * ,变成查多了其余字段, 其余字段不是索引,导致回表,慢。

问题出在哪里? 出在其余字段不是索引?

那么给其余字段都建索引呗,完事了兄弟们。

你们千万不要这么乱搞,索引的保护老本肯定是不能漠视的。

波及到批改新增删除数据时索引的保护老本,索引页的决裂合并等等。索引也是须要存起来的,也是须要占用磁盘空间的。而且如果N个字段都是索引, 轻易改变一行数据,须要保护N个索引。

什么概念,就像咱们平时写word文档,搞了个目录,而后底下的2级题目,3级题目,注释啥的,什么分页啥的,乌七八糟操作的编辑,都须要去刷新一下目录。

那么这个索引笼罩影响真的十分大吗?

拿出200W数据的表,删除全副索引,给 platform_sn 独自加索引 :

而后先试试索引笼罩的查问,看看用时,0.02秒 :

接着换成select *

当然这是 200W 数据的场景下, 不过能够看出,工夫差距还是很显著。

0.02 到 0.179 ....

如果咱们再加几个大字段?Text ... 那预计就真的离谱了 。

主观总结:

  1. 如果表里有大字段,TEXT 、BLOB系列类型字段, 应用 SELECT * 须要留神
  2. 如果原本只查问某1,2个比拟罕用的字段的,能够给这些字段建单个索引或者组合索引 ,这时候查问就防止 应用 SELECT *,尽量能触发索引笼罩是最好的了
  3. 如果表字段不多,也没啥非凡字段类型, 而且必定是查多列的,无奈触发索引笼罩的状况下,

我感觉 应用 SELECT * 也不妨,或者写个<select cloum> 外面列出所有字段,这样copy代码也不便(因为会存在一种状况就是,数据库外面有这个字段,然而不能查出来,这种状况select * 就是不如写成select <select cloum>这种形式不便了,只须要在<select cloum> 提除某个字段就 能够)。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!