1. 什么是索引?

    索引是一种用于快速查询和检索数据的数据结构。常见的索引结构有: B 树, B+树和 Hash。(索引的作用就相当于目录)


    1. 索引的优缺点?

    优点

    • 使用索引可以大大加快 数据的检索速度(大大减少检索的数据量), 这也是创建索引的最主要的原因。
    • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

    缺点

    • 创建索引和维护索引需要耗费许多时间。当对表中的数据进行增删改的时候,如果数据有索引,那么索引也需要动态的修改,会降低 SQL 执行效率。
    • 索引需要使用物理文件存储,也会耗费一定空间。

    1. 索引的底层数据结构?
    2. Hash表

    哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。
    缺点:

    • Hash冲突(解决办法 链地址法)
    • Hash 索引不支持顺序和范围查询(Hash 索引不支持顺序和范围查询是它最大的缺点)
    1. B+树

    B 树也称 B-树,全称为 多路平衡查找树 ,B+ 树是 B 树的一种变体。B 树和 B+树中的 B 是 Balanced (平衡)的意思。
    B 树& B+树两者有何异同呢?

    • B 树的所有节点既存放键(key) 也存放 数据(data),而 B+树只有叶子节点存放 key 和 data,其他内节点只存放 key。
    • B 树的叶子节点都是独立的;B+树的叶子节点有一条引用链指向与它相邻的叶子节点。
    • B 树的检索的过程相当于对范围内的每个节点的关键字做二分查找,可能还没有到达叶子节点,检索就结束了。而 B+树的检索效率就很稳定了,任何查找都是从根节点到叶子节点的过程,叶子节点的顺序检索很明显。

    B+树.png
    B+树的有点:

    • B+树是B-树的变种(PLUS版)多路绝对平衡查找树,他拥有B-树的优势。B+树扫库、表能力更强。
    • B+树的磁盘读写能力更强。
    • B+树的排序能力更强。
    • B+树的查询效率更加稳定

    1. 什么是聚集索引?

    聚集索引即索引结构和数据一起存放的索引。主键索引属于聚集索引。
    聚集索引的优点:
    聚集索引的查询速度非常的快,因为整个 B+树本身就是一颗多叉平衡树,叶子节点也都是有序的,定位到索引的节点,就相当于定位到了数据。
    聚集索引的缺点:

    • 依赖于有序的数据 :因为 B+树是多路平衡树,如果索引的数据不是有序的,那么就需要在插入时排序,如果数据是整型还好,否则类似于字符串或 UUID 这种又长又难比较的数据,插入或查找的速度肯定比较慢。
    • 更新代价大 : 如果对索引列的数据被修改时,那么对应的索引也将会被修改, 而且况聚集索引的叶子节点还存放着数据,修改代价肯定是较大的, 所以对于主键索引来说,主键一般都是不可被修改的。

    1. 什么是非聚集索引?

    非聚集索引即索引结构和数据分开存放的索引。
    非聚集索引的优点:
    更新代价比聚集索引要小 。非聚集索引的更新代价就没有聚集索引那么大了,非聚集索引的叶子节点是不存放数据的
    非聚集索引的缺点:

    • 跟聚集索引一样,非聚集索引也依赖于有序的数据
    • 可能会二次查询(回表) :这应该是非聚集索引最大的缺点了。 当查到索引对应的指针或主键后,可能还需要根据指针或主键再到数据文件或表中查询。

    1. 索引类型?
    2. 普通索引:最基本的索引(仅加速查询)
    3. 唯一索引:加速查询 + 列值唯一(可以有null)
    4. 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个组合索引
    5. 组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
    6. 全文索引:对文本的内容进行分词,进行搜索

    1. 创建索引注意事项?

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

    • 不为 NULL 的字段 :索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。
    • 被频繁查询的字段 :我们创建索引的字段应该是查询操作非常频繁的字段。
    • 被作为条件查询的字段 :被作为 WHERE 条件查询的字段,应该被考虑建立索引。
    • 频繁需要排序的字段 :索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。
    • 被经常频繁用于连接的字段 :经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。

    2.被频繁更新的字段应该慎重建立索引。
    虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了。
    3.尽可能的考虑建立联合索引而不是单列索引。
    因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。
    4.注意避免冗余索引
    冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
    5.考虑在字符串类型的字段上使用前缀索引代替普通索引。
    前缀索引仅限于字符串类型,较普通索引会占用更小的空间,所以可以考虑使用前缀索引带替普通索引。


    1. 使用索引的一些建议
    • 对于中到大型表索引都是非常有效的,但是特大型表的话维护开销会很大,不适合建索引
    • 避免 where 子句中对字段施加函数,这会造成无法命中索引。
    • 在使用 InnoDB 时使用与业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
    • 删除长期未使用的索引,不用的索引的存在会造成不必要的性能损耗 MySQL 5.7 可以通过查询 sys 库的 schema_unused_indexes 视图来查询哪些索引从未被使用
    • 在使用 limit offset 查询缓慢时,可以借助索引来提高性能

    1. 什么情况不走索引?
    • 条件中有or,但是却并不是所有条件都创建了索引
    • 使用不等于(!=或<>)
    • 对索引字段做函数操作或参与计算
    • 隐式类型转换(类型不一致),字符串与数字比较,字符串会转换为数字
    • like查询以%开头
    • 多列索引没有按照最左前缀匹配原则来查找