索引是存储引擎用来快速查询记录的一种数据结构,按实现方式主要分为Hash索引和B+树索引。
按功能划分,主要有以下几类

单列索引指的是对某一列单独建立索引,一张表中可以有多个单列索引
1. 单列索引 - 普通索引
create table student(
id int primary key,
card_id varchar(20),
name varchar(20),
index index_name(name) -- 1.创建表时,给name列创建普通索引
);
-- 2.创建表后,添加普通索引
create index index_name on student(name);
-- 3.修改表结构,添加普通索引
alter table student add index index_name(name);
show index from student;
drop index index_name on student;
-- 或
alter table student drop index index_name;
2. 单列索引 - 唯一索引
与普通索引的区别在于唯一索引列的值必须唯一,但可以有空值
create table student(
id int primary key,
card_id varchar(20),
name varchar(20),
unique index_card_id(card_id) -- 1.创建表时,给card_id列创建唯一索引
);
-- 2.创建表后,添加唯一索引
create unique index index_card_id on student(card_id);
-- 3.修改表结构,添加唯一索引
alter table student add unique index_card_id(card_id);
3. 单列索引 - 主键索引
MySQL会在主键列上自动创建索引,就是主键索引。(联合主键也会自动创建对应的组合索引)
主键列唯一且不为空,所以主键索引是特殊的唯一索引。
4. 组合索引(复合索引)
组合索引指将多个列合在一起创建索引,可以创建组合普通索引,组合唯一索引(某一列值可以重复,但两列合起来不能重复)。
-- 添加组合普通索引
create index index_card_id on student(id,card_id);
-- 添加组合唯一索引
create unique index index_card_id on student(id,card_id);
组合索引的使用符合最左原则,例如上面的索引,单独查id可以用到组合索引,单独查card_id用不到组合索引。
5. 全文索引(仅了解)
-- 添加组合普通索引
alter table t_article add fulltext index_content(content);
-- 添加组合唯一索引
create fulltext index index_content on t_article(content);
-- match后跟字段,against后跟要模糊匹配的文本
select * from t_article where match(content) against('you');
-- 查询结果与下面语句相同
select * from t_article where content like '%you%';
6. 空间索引(使用很少,仅了解)
空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有以下4种
| 空间数据类型 | 含义 | 说明 |
|---|---|---|
| Geometry | 空间数据 | 任何一种空间类型 |
| Point | 点 | 坐标值 |
| LineString | 线 | 一系列点连接而成 |
| Polygon | 多边形 | 多条线组成 |
create table shop_info(
id int primary key auto_increment comment 'id',
shop_name varchar(64) not null comment '门店名称',
geom_point geometry not null comment '经纬度',
spatial key geom_index(geom_point) -- 添加空间索引
);
索引内部原理



索引失效的各种情况
-- 创建复合索引
-- 等价于三个索引name,name + status,name + status + address
create index idx_seller_name_sta_addr on tb_seller(name,status,address);
-- 全值匹配(索引生效)
select * from tb_seller where name = '小米科技' and status = '1' and address = '北京市';
-- 最左前缀法则
select * from tb_seller where name = '小米科技'; -- 索引生效
select * from tb_seller where status = '1'; -- 索引不生效
select * from tb_seller where name = '小米科技' and address = '北京市'; -- 只有name列索引生效
-- 范围查询右边的列不能使用索引
select * from tb_seller where name = '小米科技' and status > '1' and address = '北京市'; -- 只有name和status使用索引,address没有使用索引
-- 索引列上运算则索引失效
select * from tb_seller where substring(name,3,2) = '科技'; -- 索引失效
-- 查询列尽量包含仅包含索引列
select * from tb_seller where name = '小米科技' and address = '北京市';
-- or条件不会使用索引
select * from tb_seller where name = '小米科技' or status = '1'; -- 索引失效
-- %开头的模糊查询不会使用索引
select * from tb_seller where name like '%科技'; -- 索引失效
select * from tb_seller where name like '科技%'; -- 使用索引
-- %开头的模糊查询仅包含索引则可以使用索引
select name from tb_seller where name like '%科技%'; -- 使用索引
-- in使用索引,not in不使用索引(针对普通索引来说,若为主键索引则都可以使用索引)
select * from tb_seller where name in ('小米科技','阿里巴巴'); -- 使用索引
select * from tb_seller where name not in ('小米科技','阿里巴巴'); -- 不使用索引
-- 如果有多个单列索引,只会使用一个最优的索引
-- 如果不是组合索引,而是对name,status,address分别建立单列索引,则只会使用一列索引
select * from tb_seller where name = '小米科技' and status = '1' and address = '北京市';
| Extra | 含义 |
|---|---|
| using index | 查询列仅包含索引列时 |
| using where | |
| using index condition | 查询列不仅包含索引列时(需要回原表查数据) |
| using index; using where |