索引

索引

索引是用于快速查找记录的一种数据结构,类似与书的目录。

索引类型

索引常用两种数据结构来实现:B树,B+树(hash索引,类似于HashMap结构)(根节点,子节点,叶子节点)

使用索引后,搜索引擎不需要进行全表扫描来获取数据。

B树

m阶B树具有以下特点

  • 根节点至少2个节点
  • 除根节点外,每个节点的key的数据量必须满足:m/2 <= x <= m-1(m阶树,x为节点key数量)

每个节点存储了多个key(记录的主键)及对应的信息,还存储了指针,指向子磁盘页

索引

假设这是我们user表中的数据,键值即为我们的 id ,现在我们要查找id为28的记录。

建立索引的情况下:

  1. 读取磁盘块1中的数据(已经在内存中),判断出应该读取p2指向的磁盘块3.
  2. 读取磁盘块3中的数据,判断出应该读取p2指向的磁盘块8.
  3. 读取磁盘快8的数据,查找到id为28的记录。

没有索引情况下:

扫描全表,直到查找到id为28 的记录

对比有无索引的情况,我们就可以很明显的发现,如果我们的表记录数很大,建立索引后只要保持树的深度H,我们就可以在<=H-1次下,查找到我们的记录(根节点常驻内存)。没有建立索引时,则需要进行扫描全表,很耗费系统资源,且效率非常低下

B+树

  • B+树是B树的升级版;
  • B+Tree与BTree的区别在于,B+Tree的非叶子节点只存储导航信息,数据全部存储在叶子节点处,并且用链表链接;
  • B+Tree的非叶子节点只起导航作用,这样的好处是内页可以存储更多的key,数据更紧密,降低了树的深度,降低了I/O的读取次数,提高了效率;
  • B树的节点中没有重复元素,B+树有;

Hash索引

存储引擎对所有的索引列进行hash计算,将hahs码存储在索引中,并记录每个数据行的指针。只能用于等值过滤,不能用于范围过滤,仅支持=,in等精确查询,不支持排序,不支持匹配查找。

聚集索引

它不是索引类型,是一种数据存储方式。数据行的物理顺序与列值(主键)顺序一致,一个表中只能拥有一个聚集索引(主键索引就是聚集索引,叶子节点保存了数据)。是一颗B+树,叶子节点包含了所有数据,且有序。

非聚集索引(二级索引)

在非主键的其他列上建立所以,就是二级索引。索引的逻辑顺序与磁盘上的物理存储顺序不同,一个表中可以拥有多个非聚集索引。非聚集索引在索引没有覆盖到对应的列时需要进行二次查询。叶子页包含了对应的主键值。

索引

  • 主键索引,约束比唯一索引更加严格,不允许空值,仅允许一列为主键索引,使用PRIMARY关键字
  • 唯一索引,允许空值,可允许多个列设置为唯一索引(身份证,手机号),使用UNIQUE关键字,会在新数据插入时,自动检测是否已有相同树值的记录(避免数据出现重复)
  • 普通索引,唯一任务是加快对数据的访问速度,使用在经常出现在查询条件或排序条件中的数据列,表关联查询的列上
  • 组合索引,遵循最左匹配原则
  • 全文索引,仅用于MyISAM搜索引擎

缺点

  • 创建和维护索引,耗时,并随着数据量的增加而增加
  • 索引会占用物理空间
  • 当对数据进行CUD时,索引也需要动态维护

使用场景

经常搜索的列,表关联查询的列,排序的列,区分度高的列,使用索引的列不要参与计算,使用相同类型比较,防止隐式转换,定义为text,miage,二进制的列,不应该建立索引,当表修改操作远远大于查询操作时不应该建立索引

为什么性别和其他选择性低的列不适合建立索引

因为建立索引需要耗时,访问索引都需要付出额外的擦I/O操作。假设你从100w条数据中取几条数据,利用索引快速定位,虽然查询索引进行了I/O开销,但非常有用;但是你从100w条数据中取50w条数据,所有的磁盘页基本上都访问到了,和通过全表扫描无差别。(数据存储在磁盘页,顺序存储)