为什么SELECT * 效率低

为什么SELECT * 效率低

  • 一、效率低的原因
    • 1. 不需要的列会增加数据传输时间和网络开销
    • 2. 对于无用的大字段,如 varchar、blob、text,会增加 io 操作
    • 3. 失去MySQL优化器“覆盖索引”策略优化的可能性
  • 二、索引
    • 1. 联合索引
      • 优势:
        • 1. 减少开销
        • 2. 覆盖索引
        • 3. 效率高
      • 建立索引注意事项:

一、效率低的原因

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

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

  • 用“SELECT * ”数据库需要解析更多的对象、字段、权限、属性等相关内容,在 SQL 语句复杂,硬解析较多的情况下,会对数据库造成负担。
  • 增大网络开销,* 有时会误带上如log、IconMD5之类的无用且大文本字段,数据传输size会几何增涨。如果数据库和应用程序不在同一台机器,这种开销尤其明显。
  • 即使数据库和客户端是在同一台机器上,使用的协议还是 tcp,通信也是需要额外的时间。

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

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

3. 失去MySQL优化器“覆盖索引”策略优化的可能性

  • SELECT * 杜绝了覆盖索引的可能性,而基于MySQL优化器的“覆盖索引”策略是速度极快,效率极高的。
在磁盘上有两棵 B+ 树,即聚集索引和辅助索引(包括单列索引、联合索引),分别保存(a,b,c,d,e,f)和(a,b),如果查询条件中where条件可以通过b列的索引过滤掉一部分记录,查询就会先走辅助索引,如果用户只需要a列和b列的数据,直接通过辅助索引就可以知道用户查询的数据。

如果用户使用select *,获取了不需要的数据,则首先通过辅助索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。

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

为什么SELECT * 效率低_第1张图片

二、索引

MySQL中辅助索引包括单列索引、联合索引(多列联合)

1. 联合索引

联合索引 (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)
SELECT a,b,c from table where a='条件1' and b = '条件2';

MySQL 可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机 io 操作。减少 io 操作,特别是随机 io 其实是 DBA 主要的优化策略。

在真正的实际应用中,覆盖索引是主要的提升性能的优化手段之一。

3. 效率高

索引列多,通过联合索引筛选出的数据越少。

建立索引注意事项:

1. 数据量小的表不需要建立索引,建立会增加额外的索引开销
2. 不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义
3. 经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率
4. 数据重复且分布平均的字段,因此他建立索引就没有太大的效果
5. 数据变更需要维护索引,意味着索引越多维护成本越高。

不要随意的建立索引,更多的索引也需要更多的存储空间。

你可能感兴趣的:(Mysql,数据库,mysql,数据库)