索引

什么是索引

索引是一种数据结构。就像书有目录一样,这个目录就是索引,方便我们找到具体想看的那页。它们包含着对数据表里所有记录的引用指针。

为什么使用索引

DB在执行一条SQL语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。

索引的基本原理

索引的原理就是把无序的数据变成有序的查询,把创建了索引的列的内容进行排序,对排序结果生成倒排表,在倒排表内容上拼上数据地址链,在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据。

MySQL索引

MySQL索引有使用B+树,也有使用hash表
比较:
(1)底层时间复杂度
B+树——O(logn);hash——O(1)
(2)B+树不用全量数据加载,可以按分值加载,并且更适合范围查询;hash表占空间大,范围查找时需要多次查询。

B树和B+树的简要说明

B树和AVL树(平衡二叉树) 的差别就是B树属于多叉树,又名平衡多路查找树,即一个结点的查找路径不止左、右两个,而是有多个。数据库索引技术里大量使用者B树和B+树的数据结构。一个结点存储多个值(索引)。

重点: B+树的查找过程,与B树类似,只不过查找时,如果在非叶子节点上的关键字等于给定值,并不终止,而是继续沿着指针直到叶子节点位置。因此在B+树,不管查找成功与否,每次查找都是走了一条从根到叶子节点的路径。
(解释:说白了就是在叶子节点部分加上顺序指针,在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能)
例如如果要查询key为从n到m的所有数据记录,当找到n后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。
链接: .

使用索引一定会好吗,优缺点?

优点:方便查询,缩短查询时间
缺点:
(1)创建索引,维护索引需要消耗时间,数据量越多,维护成本越高。
(2)索引要占空间,会影响表的最大存储量。
(3)对表中数据进行增加、删除和修改,索引要动态维护,降低数据维护速度。

什么样的字段不适合创建索引

(1)列的值唯一性小(可能值小),比如性别。
(2)更新频繁的表,避免建立过多的索引。
(3)数据量小的表。

创建索引的原则

1) 最左前缀匹配原则,组合索引非常重要的原则,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的顺序可以任意调整。
2)较频繁作为查询条件的字段才去创建索引
3)更新频繁字段不适合创建索引
4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)
5)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
6)定义有外键的数据列一定要建立索引。
7)对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。
8)对于定义为text、image和bit的数据类型的列不要建立索引。

索引的使用场景

(1)where

数据库索引是如何实现的 数据库索引的原理_数据库索引是如何实现的


数据库索引是如何实现的 数据库索引的原理_数据库索引是如何实现的_02


数据库索引是如何实现的 数据库索引的原理_数据库索引是如何实现的_03


(2)order by

使用order by将查询结果按照某个字段排序时,如果该字段没有建立索引,那么执行计划会将数据从硬盘分批读取到内存排序,最后合并排序结果,这个操作是很影响性能的。

但是如果我们对该字段建立索引alter table 表名 add index(字段名),那么由于索引本身是有序的,因此直接按照索引的顺序和映射关系逐条取出数据即可。而且如果分页的,那么只用取出索引表某个范围内的索引对应的数据,而不用像上述那取出所

有数据进行排序再返回某个范围内的数据。

(3)join

对join语句匹配关系(on)涉及的字段建立索引能够提高效率

索引覆盖

如果要查询的字段都建立过索引,那么引擎会直接在索引表中查询而不会访问原始数据(否则只要有一个字段没有建立索引就会做全表扫描),这叫索引覆盖。因此我们需要尽可能的在select后只写必要的查询字段,以增加索引覆盖的几率。

这里值得注意的是不要想着为每个字段建立索引,因为优先使用索引的优势就在于其体积小。

索引和引擎不可分,MySQL中的索引如何实现的呢?

MySQL包含两种存储引擎:MyISAM存储引擎,InnoDB存储引擎。
一、MyISAM存储引擎
(1)MyISAM索引实现(非聚集)
MyISAM 索引文件 和 数据文件 是 “分离的”。
(2)查找底层逻辑
a首先 MyISAM 索引文件和数据文件是分离的
b先去.myi文件查找,发现是B+树结构
c会快速从B+树的根节点依次向下定位,每一个节点是一次磁盘IO查找,最终从B+树中定位到我们需要的 key 值
d发现这个 key 值对应的 data 是一行数据的地址指针,从而直接从磁盘上面找到该数据
二、InnoDB存储引擎
(1)innoDB 表数据 和 索引存储 在一个文件中(.ibd文件)
(2)查找 的底层逻辑
a首先 InnoDB 表数据和索引存储在同一个文件中(.ibd文件)
b先去.ibd文件查找,是B+树结构
c会快速从B+树的根节点依次向下定位,每一个节点是一次磁盘IO查找,最终从B+树中定位到我们需要的 key 值
d发现这个 key 值对应的 data 直接就是需要的行数据
链接: .

索引分类

(1)单列索引:如有唯一主键,这种主键约束就是单列索引。
(2)多列索引(组合索引):查询条件不只有一个。
组合索引的触发例子
index ( name , id );
name,id是两个字段——组合索引。
触发组合索引, 必须要有name才能触发
select * from t_user where name and id ; 触发组合索引
select * from t_user where name; 触发组合索引
select * from t_user where id and name ; 触发组合索引
select * from t_user where id ; 不会触发组合索引
如何查看触发情况:就看查询的次数。使用关键字 explain
explain select * from t_user where id ;
(3)text类型,全文索引:如文章中的关键字检索。
(4)空间索引:多个维度,如微信中附近的人;游戏中找周围的人物。

创建、插入、删除索引

创建、插入、删除索引

第一种方式:在执行CREATE TABLE时创建索引

CREATE TABLE user_index2 (
 id INT auto_increment PRIMARY KEY,
 first_name VARCHAR (16),
 last_name VARCHAR (16),
 id_card VARCHAR (18),
 information text,
 KEY name (first_name, last_name),
 FULLTEXT KEY (information),//全文索引
 UNIQUE KEY (id_card)
 );


第二种方式:使用ALTER TABLE命令去增加索引
ALTER TABLE table_name ADD INDEX index_name (column_list);其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可自己命名,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。
ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。
第三种方式:使用CREATE INDEX命令创建
CREATE INDEX index_name ON table_name (column_list);
CREATE INDEX可对表增加普通索引或UNIQUE索引。(但是,不能创建PRIMARY KEY索引)
删除索引
根据索引名删除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名
alter table user_index drop KEY name;
alter table user_index drop KEY id_card;
alter table user_index drop KEY information;
删除主键索引:alter table 表名 drop primary key(因为主键只有一个)。这里值得注意的是,如果主键自增长,那么不能直接执行此操作(自增长依赖于主键索引):
需要取消自增长再行删除:
alter table user_index
– 重新定义字段
MODIFY id int,
drop PRIMARY KEY
但通常不会删除主键,因为设计主键一定与业务逻辑无关。
链接: .

本人结合其他博客和自己的想法做的学习总结,如有错误,欢迎指正交流,大家一起努力,共同进步!