索引是什么?

索引是帮助 MySQL 高效获取数据的数据结构。

索引能干什么?

提高数据查询的效率。

索引的分类

从存储结构上面来划分

  • BTree 索引(B-Tree 或 B+Tree 索引)
  • Hash 索引
  • Full-index 全文索引
  • R-Tree 索引

    从应用层次来划分

  • 普通索引

  • 唯一索引
  • 组合索引

    从数据的物理顺序与键值的逻辑顺序关系来划分

  • 聚集索引

  • 非聚集索引

    索引的原理

就是把无序的数据变成有序的查询

  1. 把创建了索引的列的内容进行排序
  2. 对排序结果进行倒排表
  3. 在倒排表内容上骗局数据地址链
  4. 在查询的时候,先拿到倒排表内容,在取出数据地址链,从而拿到具体数据

    聚集和非聚集索引区别

  • 聚簇索引:将数据存储与索引放到了一块,并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即:只有索引是相邻的,那么对应的数据一定也是相邻的存放在磁盘上;
  • 非聚簇索引:叶子节点不存储数据,存储的是数据行地址,也就是说根据索引查找到数据行的位置,再去磁盘查找数据。这个就有点类似一本书的目录,比如我们要找第三章的第一节,那我们现在这个目录里面去去找,找到对应的页码后再去对应的页码看文章。

优势:

  • 通过聚簇索引可以直接获取到数据,相比于非聚簇索引需要二次查询(非覆盖索引的情况下)效率高;
  • 聚簇索引对于范围查询的效率很高,因为其数据是按照大小排序的;
  • 聚簇索引时候在排序的场景使用,非聚簇索引不适合

劣势:

  • 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于 InnoDB 表,我们一般都会定义一个自增的 ID 列为主键;
  • 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于 InnoDB 表,我们一般定义主键为不可更新;
  • 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。二级索引的叶节点存储的是主键值,而不是行指针(非聚簇索引存储的是指针或者说是地址),这是为了减少当出现行移动或数据页分裂时二级索引的维护工作,但会让二级索引占用更多的空间;
  • 采用聚簇索引插入新值比采用非聚簇索引插入新值的速度要慢很多,因为插入要保证主键不能重复,判断主键不能重复,采用的方式在不同的索引下面会有很大的性能差距,聚簇索引遍历所有的叶子节点,非聚簇索引也判断所有的叶子节点,但是聚簇索引的叶子节点除了带有主键还有记录值,记录的大小往往比主键要大的多。这样就会导致聚簇索引在判定新记录携带的主键是否重复时进行昂贵的 I/O 代价;

聚簇索引的特性:

  • 当表存在主键时,Innodb 使用主键作为聚簇索引;
  • 当表没有主键时,Innodb 使用第一个唯一约束索引(这个唯一索引必须是不包含null列的)作为聚簇索引;
  • 当表没有主键,也没有合适的唯一索引时,Innodb 隐含创建一个包含 rowid 的聚簇索引;

我们日常工作中,根据实际情况自行添加的索引都是辅助索引,辅助索引就是一个为了需找主键索引的二级索引,现在找到主键索引再通过主键索引找数据。

索引设计原则

image.png

锁的类型有哪些

行锁与表锁

事务

image.png

B 树与 B+ 树的区别,为什么 MySQL 使用 B+ 树?

相同点:

  • 它们的节点上面都可以存在多个值;
  • 它们都是排好序的,从父节点开始,左边的都是比父节点小的值,右边都是比父节点大的值;

不同点:

  • B+Tree 的叶子节点当中存在指针;
  • B+Tree 的非叶子节点的值,在叶子节点当中都存在一份冗余值;

MySQL 慢查询该如何优化?

  • 利用 explain 检查 SQL 是否走了索引,如果没有则优化 SQL 利用索引;
  • 利用到了索引,是否是最优索引,还是利用 explain 检查;
  • 检查 SQL 查询时是否查询了过多的字段,并且利用好分页操作;
  • 检查表中数据是否过多,是否应该进行分库分表了;
  • 检查数据库实例所在的机器的性能配置是否太低,是否可以调整实例的资源;

Explain 语句结果中各个字段分表表示什么?

image.png

  • type:表示是否使用到了索引;
  • possible_keys:可能用到的索引;
  • key:实际上用到的索引;
  • rows:预估读取的记录条数;
  • key_len:实际使用到的索引长度;

索引覆盖

索引覆盖就是一个 SQL 查询时没有使用 select * 而是指定了字段,并且指定的字段都是已添加索引的字段,那么此 SQL 走完索引后不用回表,所需要的字段都在当前索引的叶子节点上存在,可以直接作为结果返回。

最左原则

当一个 SQL 想要利用索引,就一定要提供该索引所对应的字段中最左边的字段,也就是排在最前面的字段。比如 a,b,c 字段建立了一个联合索引,那么在写 SQL 时提供了 a 字段的条件,那么就能使用到联合索引。这是由于在建立 a,b,c 三个字段的联合索引时,底层的 B+ 树是按照 a,b,c 三个字段从左往右去比较大小进行排序的,所以如果想要利用 B+ 树进行快速查找也得符号这个规则。

Redis 和 MySQL 如何保证数据一致?

延迟双删,步骤:先删除 Redis 缓存数据,在更新 MySQL,延迟几百毫秒再删除 Redis 缓存数据,这样就算在更新 MySQL 时,有其他线程读了 MySQL 把老数据读到 Redis 中,那么也会被删除掉,从而把数据保持一致。