索引
索引
索引是用于快速查找记录的一种数据结构,类似与书的目录。
索引类型
索引常用两种数据结构来实现:B树,B+树(hash索引,类似于HashMap结构)(根节点,子节点,叶子节点)
使用索引后,搜索引擎不需要进行全表扫描来获取数据。
B树
m阶B树具有以下特点
- 根节点至少2个节点
- 除根节点外,每个节点的key的数据量必须满足:m/2 <= x <= m-1(m阶树,x为节点key数量)
每个节点存储了多个key(记录的主键)及对应的信息,还存储了指针,指向子磁盘页
假设这是我们user表中的数据,键值即为我们的 id ,现在我们要查找id为28的记录。
建立索引的情况下:
- 读取磁盘块1中的数据(已经在内存中),判断出应该读取p2指向的磁盘块3.
- 读取磁盘块3中的数据,判断出应该读取p2指向的磁盘块8.
- 读取磁盘快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条数据,所有的磁盘页基本上都访问到了,和通过全表扫描无差别。(数据存储在磁盘页,顺序存储)