这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记。
索引是创建在表上的,是对数据库表中的一列或者多列的值进行排序的结果,是一种有序的数据结构,通常使用B树、B+树实现。索引的核心是提高查询的速度。
优缺点
\
优点:
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
缺点:
- 时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
- 空间方面:索引需要占物理空间。
分类
物理上,分为聚簇索引和非聚簇索引。
聚簇索引:聚簇索引的叶子节点就是数据节点。在InnoDB引擎就是聚簇索引,聚簇索引默认是主键(如果表中没有定义主键,InnoDB会选择一个唯一的非空索引代替,也可以自己设置聚簇索引)。一张表内只能有一个聚簇索引,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据需要二次查找。辅助索引叶子节点存储的不再是行的物理位置,而是主键值。通过辅助索引首先找到的是主键值,再通过主键值找到数据。
非聚簇索引:非聚簇索引(主要是为了区别聚簇索引,MyISAM引擎用的就是非聚簇索引)的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。
逻辑上,分为:
- 主键索引:数据列不允许重复,不允许为NULL,一张表只能由一个主键。使用Primary Key修饰的字段会自动创建索引。(MyISAM在没有主键的情况下不会自动添加。InnoDB在没有主键的情况下,会寻找唯一且不为空的字段当主键,如果没有就创建隐藏的主键。因为InnoDB的数据和索引存放在一个文件,必须建立索引树,然后在索引树上存放数据)。
- 普通索引:最基本的索引类型,没有唯一性的限制,允许为NULL。
ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引
ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);创建组合索引
- 唯一索引:数据列不允许重复,允许为NULL。
ALTER TABLE table_name ADD UNIQUE (column); 创建唯一索引
ALTER TABLE table_name ADD UNIQUE (column1,column2); 创建唯一组合索引
- 全文索引:使用FULLTEXT参数可以设置全文索引,只支持CHAR,VARCHAR和TEXT类型的字段上,常用于数据量较大的字符串类型上,可以提高查询速度。
ALTER TABLE table_name ADD FULLTEXT (column);创建全文索引
B树/B+树
B+树和B树的操作的优势在于B+树的查找效率上:
- B树中每个节点的关键字都有data域,而B+树除了叶子节点,其他节点只有索引,也就是说同样的磁盘页B+树可以容纳更多的节点。
- B+树的范围查询更加方便,可以先找到范围下限,然后通过叶子结点的链表顺序遍历,直至找到上限即可。而B树只能先找到下限,通过中序遍历查找,直到找到上限。
创建索引的原则
- 最左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
- 较频繁作为查询条件的字段才去创建索引
- 更新频繁字段不适合创建索引
- 若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)
- 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
- 定义有外键的数据列一定要建立索引。
- 对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。
- 对于定义为text、image和bit的数据类型的列不要建立索引。
创建索引时需要注意什么?
- 非空字段:应该指定列为NOT NULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
- 取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面,可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高;
- 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高。