当前位置: 首页 > 后端技术 > Java

为什么大家都说SELECT-效率低下?

时间:2023-04-01 17:54:48 Java

不管是上班还是面试,SQL中不使用“SELECT*”的问题,都是大家听烂了的问题。追根究底,探究其原理。效率低下的原因,先看最新的《阿里java开发手册(泰山版)》中MySQL部分说明:【强制】在表查询中,不要使用*作为查询的字段列表,需要哪些字段必须明确说。描述:增加查询分析器解析成本。加减字段容易和resultMap配置不一致。无用的字段会增加网络消耗,尤其是文本类型的字段。开发手册中提到了几个原因,让我们深入了解一下:1.不必要的列会增加数据传输时间和网络开销。使用“SELECT*”数据库需要解析较多的对象、字段、权限、属性等相关内容,在SQL语句复杂、硬解析较多的情况下,会给数据库造成沉重的负担。增加网络开销;*有时会错误地包含log、IconMD5等无用且较大的文本字段,导致数据传输量呈几何级数增长。如果DB和应用不在同一台机器上,这个开销是非常明显的。即使mysql服务器和客户端在同一台机器上,使用的协议仍然是tcp,通信需要额外的时间。2、对于varchar、blob、text等无用的大字段,会增加io操作。准确的说,当长度超过728字节时,超出的数据会先被序列化到另一个地方,所以读取这条记录会加一个io操作。(MySQLInnoDB)3.失去MySQL优化器“覆盖索引”策略优化的可能性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+树的查询,速度必然会慢很多。由于辅助索引比聚簇索引的数据少很多,所以很多时候辅助索引是用来覆盖索引(用户需要的所有列都可以通过索引获取),不需要读取磁盘,而且是直接从内存中访问,而聚簇索引很可能数据在磁盘(外存)中(取决于缓冲池的大小和命中率)。这种情况下,一个是内存读取,一个是磁盘读取。速度差异非常显着,几乎是一个数量级的差异。IndexKnowledgeExtension上面提到了辅助索引。在MySQL中,辅助索引包括单列索引和联合索引(多列联合)。单列索引这里就不详细介绍了。联合索引(a,b,c)联合索引(a,b,c)实际上建立了三个索引(a),(a,b),(a,b,c)我们可以把联合索引看成是本书一级目录,二级目录,三级目录,如index(a,b,c),表示a为一级目录,b为一级目录下的二级目录-级目录,c为二级目录下的三级目录。要使用一个目录,首先要使用它的父目录,一级目录除外。联合索引的优点1)减少开销构建一个联合索引(a,b,c)其实相当于构建三个索引(a),(a,b),(a,b,c)。每个额外的索引都会增加写操作和磁盘空间的开销。对于数据量大的表,使用联合索引会大大减少开销!2)联合索引(a,b,c)的覆盖索引,如果有如下sql,SELECTa,b,cfromtablewherea='xx'andb='xx';那么MySQL可以直接遍历索引获取Data,不需要回表,减少了很多随机io操作。减少io操作,尤其是随机io,其实是DBA的主要优化策略。因此,在实际应用中,覆盖索引是提高性能的主要优化方法之一。3)索引列越高效,通过联合索引过滤的数据越少。比如有1000W条数据的表有如下SQL:selectcol1,col2,col3fromtablewherecol1=1andcol2=2andcol3=3;假设:假设每个条件都能过滤掉10%的数据。A、如果只有单列索引,那么可以通过索引筛选出1000W10%=100w条数据,然后回表从表中找到满足col2=2和col3=3的数据100w条数据,然后排序分页。等等(递归);B、如果是(col1,col2,col3)联合索引,通过三列索引10%10%*10%=1w过滤掉1000w,效率提升可想而知!4)建立的索引越多越好吗?答案自然是否定的。数据量小的表不需要建立索引,创建会增加额外的索引开销。不要为不经常引用的列建立索引,因为它们不常用,即使建立索引也没有多大意义。不要为频繁更新的列建立索引,因为它肯定会影响插入或更新的效率。数据重复均匀分布的字段,建索引影响不大(比如性别字段,只有男和女,不适合建索引)数据变化需要维护索引,也就是说索引越多,索引越高维修费用。更多的索引也需要更多的存储空间。如果本文对您有帮助,请关注点赞`,您的支持是我继续创作的动力。转载请注明出处!