侧边栏壁纸
博主头像
BinArTale's Blog 博主等级

行动起来,活在当下

  • 累计撰写 6 篇文章
  • 累计创建 21 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

MySQL中索引

binbin
2025-04-06 / 1 评论 / 0 点赞 / 11 阅读 / 0 字

1. 索引的介绍

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

索引底层数据结构有很多类型,常见的索引结构有:B树、B+树、Hash和红黑树。在MySQL中,无论是Innodb还是MyISAM,都使用了B+树作为索引结构。

优点:使用索引可以很大程度上加速数据检索的速度,减少I/O次数。

缺点:维护索引需要耗费资源,当对表中的数据进行增删改的话,如果数据有索引,那么对应的索引也需要动态的修改。并且索引也需要占用一定的存储空间

‼️:索引不一定能够提高查询性能,如果数据量不大的情况下,使用索引有时候还不如直接全表扫描来得快。

2. 索引底层的数据结构

B+Tree:无论是 InnoDB 引擎还是 MyISAM 引擎都是使用 B+Tree 作为索引的结构,因为其支持范围查询和顺序查询,且相比于 B树 具有更稳定的查询效率和更少的 I/O 次数。

InnoDB和MyISAM中B+树的不同

  • InnoDB 中主索引的叶子节点是会存储完整的记录信息的,所以 InnoDB 表数据本身就是主索引,其余索引都被称为辅助索引,他们的叶子节点不存储完整的记录信息,只存储 key 和主键的值,因此一般情况下,使用辅助索引进行查询需要进行回表操作,也就是会回到主索引中查询完整的数据(当然覆盖索引除外)

  • MyISAM中,B+Tree 的叶节点的 data 域存储的是记录的地址,所以相比于 InnoDB ,MyISAM 的 I/O 次数会相对较多。

3. 索引类型:

  • 主键索引:列值唯一,且不能为null,可以加速查询

  • 唯一索引:列值唯一,可以为null,也可以加速查询

  • 覆盖索引:一个索引包含要查询的所有字段,也就是我们的查询内容和条件都在覆盖索引的字段中,那么使用覆盖索引:可以直接获取到所需的所有数据,可以防止回表,加快查询速度。

  • 普通索引:可以加速查询

  • 全文索引:对文本内容进行分词,然后搜索,只varchar chartext列上可以创建,但是一般不会用,该功能一般用搜索引擎嗲提,ElasticSearch

  • 前缀索引:对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符。

  • 联合索引:多个列构成一个索引,专门用于组合搜索,其效率大于索引合并(但是会有最左前缀问题)

最左前缀匹配原则:使用联合索引时,MySQL 会根据索引中的字段顺序,从左到右一次匹配查询条件中的字段,如果查询条件与索引中的最左侧字段相匹配,那么MySQL就会使用索引来过滤数据,这样可以提高查询数据。当碰>、<时,会停止匹配(当前条件可以用上),但是碰 >= 、<= 、between、like 的时候,不会停止匹配,联合索引依旧可以用到。

索引下推(Index Condition Pushdown,ICP):它允许存储引擎在索引遍历过程中,执行部分 where 语句的判断条件(索引失效时,使用判断条件先过滤掉一些肯定不满足的数据),直接过滤掉不满足条件的记录,从而减少回表的次数

4. 使用索引的建议

  1. 选择合适的字段创建:

    1. 不为 null 的字段:对于数据为 null 的字段,数据库比较难优化,如果字段频繁查询,但是又避免不了为null,建议使0/1、true/false 这样语义较为清晰的短值或短字符作为替代。

    2. where子句中的列:为频繁出现在 where 条件中的列创建索引,尤其是筛选数据比例较小的列

    3. 连接 join:为表连接的列创建索引,加速关联查询。

    4. 高选择性的列:选择区分度高的列(如唯一ID、用户账号等)。

    5. 排序和分组列:为尝出现在 order bygroup by 中的列创建索引,避免额外的排序操作

    6. 频繁更新的列,应该尽量不设置索引

  1. 限制每张表上的索引数量,单张表索引尽量不超过5个,维护太多索引的会降低数据更新的效率。

  2. 尽量尽力联合索引,而不是单列索引,首先,每个索引都会占用一定的磁盘空间,也就是每个索引代表一颗 B+Tree,建立联合索引可以节约很大的磁盘空间,并且更新数据的操作效率也会提升。

  3. 避免冗余索引,也就是,联合索引(a,b),可以命中,那么索引a,也就可以命中。

  4. 避免索引失效:

    1. 隐式类型转换:比如字符串列用数字查询 where str=111会导致索引失效

    2. 函数或表达式:where YEAR(date_col)=2025无法使用索引,需改写为范围查询

    3. 前导通配符:LIKE '%abc'无法使用索引,LIKE 'abc%'可以。

    4. or 条件不当:若 or 两侧的列均有索引,可能触发索引合并,否则可能全表扫描。

0

评论区