Mysql索引


参考文章: javaGuide Mysql索引

索引概览

索引是一种用于快速查询和检索数据的数据结构,本质是一种排序好的数据结构。

索引底层数据结构

索引的底层数据结构包括:B 树,B+树,红黑树,Hash 等,不管是 InnoDB 还是 MyIasm 存储引擎都是采用的 B+树



B树和 B + 树 区别: B树每个节点都存数据,矮胖树 ;B+树只在叶子节点存储,且可以横向查找范围内的元素

索引的优缺点

  1. 优点
  • 使用索引可以极大的加快数据库检索数据的效率(减少了需要查询的数据量)
  1. 缺点
  • 建立索引和维护索引的过程太耗时。如果需要建立索引的数据量很大,建立索引的过程和进行数据更新操作时的索引动态更新过程的时间消耗是很大的。
  • 建立索引还需要占用很大的物理存储空间

    在数据量不是很大的情况下,建立索引不一定比不加索引效率更高。

聚簇索引和非聚簇索引

也称聚集和非聚集(二级索引)。

聚集索引

聚簇索引:将索引和数据都放到一起的索引,叶子节点存储行记录(数据)。

必须有,因为要存储行数据,且只有一个。

选取原则:如果存在主键,则主键索引就是聚簇索引。如果没有主键则将一个唯一索引(UNIQUE 修饰)作为聚簇索引。再没有,其底层就会创建一个虚拟的隐藏 rowid 作为聚集索引。

非聚集索引

数据和索引分开存储,叶子节点只存储这条数据的主键值。
如下图,聚集索引和非聚集索引的案例:

覆盖索引

覆盖索引: 就是查询的时候使用索引进行查询,返回的列必须在索引中全部找到。
例子:

  1. 聚集索引,根据 id 建立的索引,能够返回所有列,因此是覆盖索引
  2. 非聚集索引不一定不是覆盖索引: 如果根据 name 建立的索引,只需要查询 id 和 name ,那么也是覆盖索引。
  3. 如果查询的列在一个非聚集索引中查不完,那就需要进行回表查询

    因此最好少使用 select * 查询,避免回表查询。

索引的 sql 语法

包括创建、查看、删除索引。

索引分类

创建

  1. 这里加上 UNIQUE 就是唯一索引,加上 FULLTEXT 就是全文索引,不加就是常规索引。
  2. ON 后面的表名 + 括号,指明了需要建立索引的列,如果是一个属性,就是单列索引,多列就是联合索引(组合索引)。

查看索引

show INDEX FROM table_name

删除索引

DROP INDEX index_name ON table_name 即删除某个表 table_name 的索引 index_name

索引失效的情况

主要包括三种情况:违反最左前缀法则、索引列运算、OR 连接的条件

最左前缀法则(主要)

概念:如果使用了联合索引,查询时会先从索引最左边的字段开始查询,并且不能跳过索引中的字段。

觉得不太清晰可以去看 JavaGuide :索引最左前缀

准备一个联合索引
一个根据专业 pro、年龄 age、状态 status 建立的索引。(假设 pro 是索引最左列)

失效情况

下面失效情况都统一为查询时的条件出现的问题,可以用 explain 分析。

  1. 索引全部失效:查询条件只查询了除 pro 以外的列,比如组合 (age) (status) (age, status) 都不会使用到索引。

  2. 索引部分失效:如果是跳跃字段:如 (pro, status),中间没有 age,查询只会走 pro 的索引,而不会走 status 索引。

    注意,只要包括最左列即可使用到索引,与条件中设置的顺序无关,如组合 (age, status, pro)顺序不是 pro 首位,但是也会使用到整个索引。

  3. 范围查询条件(如 > 或 <)之后的字段不会走索引,如 (pro, age > 10, status)只有 status 不会走索引。

    但是对于 >=<=BETWEENlike 前缀匹配的范围查询,并不会停止匹配。

索引列上的运算

在索引列上进行计算、函数、类型转换等操作;

  • 比如取子串函数 substring、数值运算 a + b、连接函数 concat 等。
  • 还有类型转换:包括”隐式类型转换”,如不加引号的字符串,可能会进行类型转换导致索引失效。详情参考:MySQL隐式转换造成索引失效

使用 OR 条件

查询条件中使用 OR,且 OR 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;

其他情况

  1. 字符串首部模糊匹配,如 like ‘%abc’
  2. IN 的范围过大,导致索引失效

索引设计原则

从索引建立和使用来优化查询效率。

  1. 针对数据量大,且查询较频繁的表建立索引

  2. 将经常作为查询条件、分组条件、排序条件的字段建立索引

  3. 尽量使用唯一索引,提高索引使用效率。(唯一索引查询到的数据只有一条)

  4. 如果要根据字符串类型的字段建立索引,如果过长可以建立”前缀索引“,减少空间的使用。

    前缀索引:以某个字段字符串的前几个字符为准建立索引,语法:create index index_name on table_name(str(n)) n 为截取的字符个数

  5. 如果涉及到多个字段的查询,尽量建立联合索引,实现覆盖索引,避免回表查询,提高效率。

  6. 避免索引冗余:多个索引的功能有重复,造成空间浪费。


文章作者: KTpro
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 KTpro !
  目录