携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
1.索引概述
索引是帮助MySQL高效获取数据的数据结构。在没有索引时,查询数据会进行全表扫描,查询速度慢,创建索引后,会在指定的字段上形成一个索引的数据结构,如二叉树,减少磁盘I/O次数,从而大大提升查询的效率。
2.索引的优缺点
优点:
- 提高数据的检索效率,降低数据库的I/O成本。
- 创建唯一索引,保证每行数据的唯一性。
- 加速表与表之间的连接,增加查询效率。
- 减少查询中分组和排序的时间。
缺点:
- 创键的索引为数据结构,会占用磁盘空间。
- 创建和维护索引需要耗费时间。
- 降低更新表的速度,会影响DML语句的效率(需要对索引进行维护)
索引可以提高查询速度但会影响插入记录的速度,可以先删除索引,再插入数据,所有数据插入之后重新创建索引
3.索引的分类
- 从功能逻辑上分为4种:普通索引、唯一索引、主键索引、全文索引
- 按照物理实现方式分为2种:聚簇索引和非聚簇索引
- 按照作用字段个数分为:单列索引和联合索引
- 从底层实现分为:B+Tree索引、B-Tree索引和Hash索引
3.1.普通索引
没有任何附加限制条件,只是用于提高查询效率。普通索引可以创建在任何数据类型上,其值是否唯一和非空由字段本身的完整性约束条件决定。
3.2.唯一索引
使用UNIQUE参数可以设置索引为唯一性索引,在创建唯一性索引时,限制该索引的值必须是唯一的。
3.3.聚簇(主键)索引
聚簇索引是InnoDB存储引擎中(MyISAM不支持聚簇索引)的一中数据存储方式,所有的用户记录都存储在了叶子结点上,数据和索引是一个文件(.idb),也就是:数据即索引。
聚簇索引的特点:
- 记录主键值的大小进行页的排序:
- 页内的记录按照主键的大小顺序排成一个单向链表。
- 各个页之间根据页内主键大小排成一个双向链表。
- 存放目录项的页分为不同层次,同一层次中各个页排成一个双向链表。
- B+树的叶子结点存储了完整的用户记录(所有列的值)。
- InnoDB存储引擎会自动根据主键创建聚簇索引,不需要手动创建。
- MyISAM不支持聚簇索引。
- 每个表只能有一个聚簇索引,一般是主键
- 若没有定义主键,InnoDB会选择非空的唯一索引代替;若没有,InnoDB会隐式定义一个主键作为聚簇索引
- 为了充分利用聚簇的特性,主键列尽量选用有序的ID
聚簇索引的优点:
- 数据访问更快,因为将数据和索引保存在同一个B+树中。
- 对于主键的排序查找和范围查找速度非常快,节省I/O操作。
聚簇索引的缺点:
- 插入速度严重依赖插入顺序,按照主键的顺序插入是最快的方式,否则会出现
页分裂(将当前页面分裂成两个页面,本页面的一些记录移动到新创建的页面)。因此一般定义一个自增的列为主键。 - 更新主键的代价很高,因为更新会导致该行移动。因此一般定义主键不可更新。
InnoDB为什么采用B+树:
- 数据库查询经常会出现非等值查询,哈希索引在这种情况下无法工作。
- 相比于B树,B+树索引非叶子节点不存放数据,因此其内部结点相对B树更小,从而磁盘一次IO可以读取更多的索引数据,有效减少磁盘IO次数。
- 数据库查询经常会出现范围查询,B+树底层的叶子节点之间按照顺序排列,可以更有效的实现范围查询。
3.4.非聚簇索引(二级索引)
区别于聚簇索引,数据与索引分离。
非聚簇索引特点:
- 使用非主键字段作为数据页的排序规则。
- 叶子结点中记录的不是完整的用户记录,而是作为索引的关键字段和主键这两列的值(如果是联合索引则多列)。
- 根据索引的关键字段来查询一条完整的用户记录时,需要通过两次索引查找:通过找到的主键值再到聚簇索引中进行回表,从而找到完整的记录。
- 一张表可以存在多个非聚簇索引。
MyISAM索引方案:
- MyISAM中所有索引都是非聚簇索引。
- 数据文件(.MYD)和索引文件分开存储(.MYI)。
- B+树索引的叶子结点的data域存放的是对应.MYD文件中数据记录的地址。
- MyISAM中所有索引都有回表操作,且回表速度比InnoDB快,因为直接得到地址偏移量。
InnoDB索引与MySAM索引对比:
3.5.单列索引
在表中的单个字段上创建索引,只针对该字段。一个表可以有多个单列索引。
3.6.联合(多列)索引
在表的多个字段上创建索引,只有查询条件使用了这些字段的第一个字段时才会被使用。使用组合索引时遵循最左前缀匹配。
最左前缀匹配:
在MySQL建立联合索引时会遵循最佳左前缀原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。
对于联合索引,过滤条件要使用索引必须按照索引建立的顺序,依次满足,一旦跳过某个字段,索引后面的字段都无法使用。如果查询条件中没有使用第一个字段,联合索引不会被使用。
3.7.Hash索引
Hash索引只在Memory存储引擎中被支持。通过Hash算法大幅提升检索数据的效率。
与树形索引对比:
- Hash索引仅能满足等值查询,范围查询时时间复杂度会退化为O(n),而树形索引因为有序的特性,能维持O(logn)
- Hash索引存储的数据是没有顺序的,在
order by情况下需要重新排序 - 联合索引情况下,Hash值是将索引键合并后计算的,无法对单独的键进行查询
- 索引列的重复值较高的情况下,会降低Hash索引的效率,因为遇到冲突时,要遍历桶中的行指针进行比较查询关键字
InnoDB提供自适应Hash:
- 当某个数据经常被访问,就会将这个数据的地址存放到Hash表中,下次查询时可以直接找到页面的所在位置。这样让B+树也具备了Hash索引的优势。
- 自适应Hash可以根据查询条件加速定位到叶子结点,特别是当B+树比较深时,可以明显提高检索效率。
3.8.全文索引
也称全文检索,是目前搜索引擎的关键技术。比较适合大型数据集。
使用FULLTEXT参数可以设置为全文索引,在定义索引的列上支持值的全文查找,允许在这些列中添加重复值和空值。全文索引只能在CHAR、VARCHAR、TEXT及其系列类型的字段上。
3.9.空间索引
使用参数SPATIAL可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中的空间数据类型包括GEOMETRY、POINT、LINESTRING和POLYGON等。目前只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。对于初学者来说,这类索引很少会用到。