看着你满怀期待的脸
不经意间
冲破了我对你的平淡
心头一酸
内心又有点波澜
这是否存在隐患
还是暗示某种惨淡
关于MYSQL语句优化的问题,老生常谈,什么尽量避免使用SELECT * ,尽量避免条件使用or,加上limit限制行数…
就在上周,公司的一个项目,功能是在发布文章时不发布保存草稿后,打开草稿重新发布时,地区的name不显示的BUG,主管让我排查了代码,原来是在写sql语句时没有对地区name的字段进行查询。
这时候我勤劳的优点就展现出来了,把那几个字段加上就好了,虽然脑海里浮现出了一个小星星,没错,就是你想的那个小星星。哎呀,真香!(我们公司项目不是很大,数据量也上不去,性能上还没有遇到瓶颈,所以比较放纵哈)
大家不要学我哈,代码优化的必要性还是非常重要的。
首先我们先看一下最新发布的《阿里JAVA开发手册泰山版》中是这样说的
关注文末公众号,回复 ‘’手册‘’ ,可获取阿里JAVA开发手册最新版
MYSQL在执行查询语句需要经过很多阶段的处理,拿到数据也会进行一些处理,这里不过多了解。
而你给出实际需要查询的字段,mysql内部会针对你所查询的字段进行必要优化处理,而查询所有字段在mysql内部虽然也会优化,但优化方案可能会针对其他不需要的字段进行优化处理,效率定然会有所差异。
这个就比较好理解了,相信用过ORM(对象关系映射)的框架的伙伴们秒懂,使用 * 自然需要实体类和数据库字段一一对应(或者进行一一对应的配置)方能舒服的使用。
不需要的字段会增加数据传输时间和网络开销
用 SELECT * 的话,数据库需要解析更多的对象,字段,权限,属性等相关内容,在SQL语句复杂,硬解析解析较多的情况下,会对数据库造成沉重的负担。
增加网络开销
有时会误带上入log,lconMD5之类的无用且大文本大内容字段,数据传输size会几何增涨。如果DB和应用程序不在同一个服务器,进行数据传输的开销就不用多说了吧
即使 mysql 服务器和客户端是在同一台机器上,使用的协议还是 tcp,通信也是需要额外的时间。
IO操作
对于无用的大字段,如 varchar、blob、text,会增加 io 操作
准确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个地方,因此读取这条记录会增加一次 io 操作。(MySQL InnoDB)
SELECT * 杜绝了覆盖索引的可能性,而基于MYSQL优化器的“覆盖索引”策略又是速度极快,效率极高,业界极为推荐的查询优化方式。
例如,有一个表为t(a,b,c,d,e,f),其中,a为主键,b列有索引。
那么,在磁盘上有两棵 B+ 树,即聚集索引和辅助索引(包括单列索引、联合索引),分别保存(a,b,c,d,e,f)和(a,b),如果查询条件中where条件可以通过b列的索引过滤掉一部分记录,查询就会先走辅助索引,如果用户只需要a列和b列的数据,直接通过辅助索引就可以知道用户查询的数据。
如果用户使用select *,获取了不需要的数据,则首先通过辅助索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。
由于辅助索引的数据比聚集索引少很多,很多情况下,通过辅助索引进行覆盖索引(通过索引就能获取用户需要的所有列),都不需要读磁盘,直接从内存取,而聚集索引很可能数据在磁盘(外存)中(取决于buffer pool的大小和命中率),这种情况下,一个是内存读,一个是磁盘读,速度差异就很显著了,几乎是数量级的差异。
MYSQL设计了这么好的覆盖索引,我们还是要对的起MYSQL的良苦用心的哈
答案自然是否定的
部分摘选自博客—>>>_陈哈哈
文章持续更新,可以微信搜索「 绅堂Style 」第一时间阅读,回复【资料】有我准备的面试题笔记。
GitHub https://github.com/dtt11111/Nodes 有总结面试完整考点、资料以及我的系列文章。欢迎Star。