Skip to main content

moregeek program

mysql 为什么 select * 比 select 字段效率低?_wx5f5ed5b01c9a8的博客-多极客编程

    看到很多资料在介绍sql优化时常说select * 效率是最低的,“*” 表示通配所有字段,在SQL的机制里,需要先识别统计所有字段再进行下一步。明确指定字段的话,会减少上述的操作,所以效率有所提升。但是我觉得这个说法有问题。

 

    无论在工作还是面试中,关于SQL中不要用“SELECT *”,都是大家听烂了的问题,虽说听烂了,但普遍理解还是在很浅的层面,并没有多少人去追根究底,探究其原理。

废话不多说,本文带你深入了解一下"SELECT * "效率低的原因及场景。

一、效率低的原因

在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。

说明:

  • 增加查询分析器解析成本。
  • 增减字段容易与 resultMap 配置不一致。
  • 无用字段增加网络 消耗,尤其是 text 类型的字段。

开发手册中比较概括的提到了几点原因,让我们深入一些看看:

1. 不需要的列会增加数据传输时间和网络开销

用“SELECT * ”数据库需要解析更多的对象、字段、权限、属性等相关内容,在 SQL 语句复杂,硬解析较多的情况下,会对数据库造成沉重的负担。

增大网络开销;* 有时会误带上如log、IconMD5之类的无用且大文本字段,数据传输size会几何增涨。如果DB和应用程序不在同一台机器,这种开销非常明显

即使 mysql 服务器和客户端是在同一台机器上,使用的协议还是 tcp,通信也是需要额外的时间。

2. 对于无用的大字段,如 varchar、blob、text,会增加 io 操作

准确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个地方,因此读取这条记录会增加一次 io 操作。(MySQL InnoDB)

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+树查询,速度必然会慢很多。

Mysql 为什么 select * 比 select 字段效率低?_联合索引



由于辅助索引的数据比聚集索引少很多,很多情况下,通过辅助索引进行覆盖索引(通过索引就能获取用户需要的所有列),都不需要读磁盘,直接从内存取,而聚集索引很可能数据在磁盘(外存)中(取决于buffer pool的大小和命中率),这种情况下,一个是内存读,一个是磁盘读,速度差异就很显著了,几乎是数量级的差异。

二、索引知识延申

上面提到了辅助索引,在MySQL中辅助索引包括单列索引、联合索引(多列联合),单列索引就不再赘述了,这里提一下联合索引的作用

  • 联合索引 (a,b,c)

联合索引 (a,b,c) 实际建立了 (a)、(a,b)、(a,b,c) 三个索引

我们可以将组合索引想成书的一级目录、二级目录、三级目录,如index(a,b,c),相当于a是一级目录,b是一级目录下的二级目录,c是二级目录下的三级目录。要使用某一目录,必须先使用其上级目录,一级目录除外。

如下:

where条件

效果

where a=1 and c=1

只使用了一级目录,c在三级目录,没有使用二级目录,那么三级目录时没法使用

where a=l and b=1

只使用了—级目录,二级目录

  • 联合索引的优势

1) 减少开销

建一个联合索引 (a,b,c) ,实际相当于建了 (a)、(a,b)、(a,b,c) 三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销!

2)覆盖索引

对联合索引 (a,b,c),如果有如下 sql 的,

SELECT a,b,c from table where a=\'xx\' and b = \'xx\';

那么 MySQL 可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机 io 操作。减少 io 操作,特别是随机 io 其实是 DBA 主要的优化策略。所以,在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。

3)效率高

索引列多,通过联合索引筛选出的数据越少。比如有 1000W 条数据的表,有如下SQL:

select col1,col2,col3 from table where col1=1 and col2=2 and col3=3;

假设:假设每个条件可以筛选出 10% 的数据。

A. 如果只有单列索引,那么通过该索引能筛选出 1000W10%=100w 条数据,然后再回表从 100w 条数据中找到符合 col2=2 and col3= 3 的数据,然后再排序,再分页,以此类推(递归);

B. 如果是(col1,col2,col3)联合索引,通过三列索引筛选出 1000w10% 10% *10%=1w,效率提升可想而知!

索引是建的越多越好吗

答案自然是否定的

数据量小的表不需要建立索引,建立会增加额外的索引开销

不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义

经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率

数据重复且分布平均的字段,因此他建立索引就没有太大的效果(例如性别字段,只有男女,不适合建立索引)

数据变更需要维护索引,意味着索引越多维护成本越高。

更多的索引也需要更多的存储空间

三、心得体会

相信能看到这里这老铁要么是对MySQL有着一腔热血的,要么就是喜欢滚鼠标的。来了就是缘分,如果从本文学到了东西,请不要吝啬手中的赞哦,拒绝白嫖~

有朋友问我,你对SQL规范那么上心,平时你写代码不会用SELECT * 吧?

咋可能啊,天天用。。代码里也在用(一脸羞愧),其实我们的项目普遍很小,数据量也上不去,性能上还没有遇到瓶颈,所以比较放纵。

写本篇文章主要是这个知识点网上总结的很少很散,也不规范,算是给自己也是给大家总结一份比较详细的,值得记一下的。以后给面试官说完让他没法找你茬。


©著作权归作者所有:来自51CTO博客作者游戏开发司机的原创作品,请联系作者获取转载授权,否则将追究法律责任

推荐系统从入门到实战——flask框架的使用_qq5b42bed9cc7e9的博客-多极客编程

Flask框架的使用​​Flask框架的使用​​​​Flask简介​​​​Flask环境配置​​​​安装virtualenv​​​​创建虚拟环境​​​​激活环境​​​​安装包​​​​测试安装​​​​主要内容​​​​路由​​​​route装饰器​​​​add_url_rule()​​​​指定HTTP方法​​​​匹配动态URL​​​​匹配动态URL​​​​URL构建方法​​​​请求,响应及会话​​​​

推荐系统实战——自动化构建用户以及物料画像_qq5b42bed9cc7e9的博客-多极客编程

自动化构建用户以及物料画像​​自动化构建用户以及物料画像​​​​意义​​​​新物料来源​​​​物料画像的更新​​​​物料更新添加入redis​​​​合并,物料画像构建逻辑​​​​用户侧画像的构建​​​​画像自动化构建​​​​用户画像更新脚本: process_user.py​​​​最后将上面三个脚本穿起来的shell脚本offline_material_and_user_process.sh​​​

如何对查询结果进行排序_zhang_shiwei的博客-多极客编程

1. 单列排序我们先来看下不排序的结果:SELECT prod_name FROM products;运行结果如下:接下来我们对 prod_name 列进行排序。排序使用 ORDER BY 关键字,后面跟着要排序的列。例如:SELECT prod_name FROM products ORDER BY prod_name;运行结果如下:可以看到结果按照升序进行了排序。当我们不明确指定排序的顺序时,

zadig 和 chatops 能擦出火花吗_乔克叔叔的博客-多极客编程

大家好,我是乔克,一个爱折腾的运维工程,一个睡觉都被自己丑醒的云原生爱好者。 作者:乔克 公众号:运维开发故事 博客:www.jokerbai.com 背景介绍 Zadig 是目前很火的云原生持续交付平台,具备灵活易用的高并发工作流、面向开发者的云原生环境、高效协同的测试管理、强大免运维的模板库、客观精确的效能洞察以 及云原生 IDE 插件等重要特性,为工程师提供统一的协作平面,可以满足大

istio ambient mesh七层服务治理图文详解_华为云开发者社区的博客-多极客编程

摘要:本文主要集中剖析Ambient mesh七层服务治理相关内容。本文分享自华为云社区《​​Istio Ambient Mesh七层服务治理图文详解​​》,作者:华为云云原生团队。由于Ambient mesh的工作原理比较复杂,我们在上一篇文章《​​深度剖析!Istio共享代理新模式Ambient Mesh​​》中主要剖析了Ambient mesh四层流量治理。因此本文主要集中剖析七层治理部分。

极速体验docker容器健康_github.com/zq2599的博客-多极客编程

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本文目是体验docker容器的健康检查功能,以体验为主不涉及开发,与开发相关的内容会在后面的文章细说。 关于容器健康检查 考虑这样的情况:docker环境中,springboot应用的容器还在,但已无法提供服务(例如数据或文件被破坏,线程池等资

推荐系统从入门到实战——flask框架的使用_qq5b42bed9cc7e9的博客-多极客编程

Flask框架的使用​​Flask框架的使用​​​​Flask简介​​​​Flask环境配置​​​​安装virtualenv​​​​创建虚拟环境​​​​激活环境​​​​安装包​​​​测试安装​​​​主要内容​​​​路由​​​​route装饰器​​​​add_url_rule()​​​​指定HTTP方法​​​​匹配动态URL​​​​匹配动态URL​​​​URL构建方法​​​​请求,响应及会话​​​​

推荐系统实战——自动化构建用户以及物料画像_qq5b42bed9cc7e9的博客-多极客编程

自动化构建用户以及物料画像​​自动化构建用户以及物料画像​​​​意义​​​​新物料来源​​​​物料画像的更新​​​​物料更新添加入redis​​​​合并,物料画像构建逻辑​​​​用户侧画像的构建​​​​画像自动化构建​​​​用户画像更新脚本: process_user.py​​​​最后将上面三个脚本穿起来的shell脚本offline_material_and_user_process.sh​​​

【经验】通过jvm调优,让凯哥个人博客响应速度提升了不少_凯哥java的博客-多极客编程

为什么你的个人博客访问慢?​不知道大家有没有注意到,在22.10.31 21点之后,凯哥的个人博客站点(凯哥Java:www.kaigejava.com)访问速度提升了不少。那是因为凯哥对站点做了优化。本文就记录优化方面:​优化从以下几个方面入手的:​1:JVM调优​2:日志打印​3:删除已经不用的代码​前提条件:​凯哥个人博客,是购买阿里云最廉价的机器。配置如下:1C2G1M的共享性。​一:JV

vant-weapp实现省市区三级联动顶部弹出列表_尔嵘的博客-多极客编程

准备:利用vant weapp做的顶部弹出的省市区三级联动对话框 1.下载区域:arrea.js,放到utils备用// 三级联动省市区export default { province_list: { 110000: '北京市', 120000: '天津市', 130000: '河北省', 140000: '山西省', 150000: '内蒙古自治区', 2

【服务器数据恢复】xen server存储库(sr)常见故障的数据恢复方案_sun的博客-多极客编程

​xen server存储库常见故障: 1、sr无法识别,所有虚拟磁盘(vdi)丢失。 2、sr中的虚拟磁盘(vdi)访问时报错。 3、虚拟磁盘(vdi)删除或丢失。 4、快照(snapshot)删除或丢失。 5、sr初始化。 6、sr所在的LVM结构损坏。 7、sr所属的PV分区表损坏。 8、其他故障。  xen server存储库常见故障分析: 上述故障是用户界面层的常见故障表现,解决这些故

cros 跨域请求原理_kieary的博客-多极客编程

cros 分为两种请求简单请求浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(预检请求)(not-so-simple request)。只要同时满足以下两大条件,就属于简单请求。(1) 请求方法是以下三种方法之一: HEADGETPOST (2)HTTP请求头信息不超出以下几种字段: AcceptAccept-LanguageContent-LanguageLa