乐趣区

关于java:面试官问为啥不建议使用-Select-请你大声地回答他

作者:小指标青年 \
起源: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、longtext

tinybob、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 开发手册(嵩山版)》最新公布,速速下载!

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

退出移动版