MySQL 中使用索引
创建索引之后都会生成一棵索引树,创建多少索引生成多少棵索引树。生成的索引树也是会占用磁盘空间的,索引树越多,对增、删、改的效率影响越大;因此在创建索引之前,需要慎重考虑是否真的需要创建该索引。
目录
一、自动创建索引
二、手动创建索引
2.1 主键索引
2.2 唯一索引
2.3 普通索引
三、创建符合索引
四、查看索引
五、删除索引
5.1 删除主键索引
5.2 删除其他索引
六、创建索引的注意事项
七、如何查看 SQL 语句走没走索引
7.1 不加条件,查询所有数据
7.2 使用主键查询
7.3 查询条件符合最左前缀原则(会走索引)
7.4 查询条件不符合最左前缀原则(索引失效)
7.5 索引覆盖(高效使用索引)
7.6 总结
一、自动创建索引
当我们为一张表添加主键约束(primary key),外键约束(foreign key),唯一约束(unique)时,MySQL 会为对应的列主动创建一个索引;
如果表不指定任何约束时,MySQL 会自动为每一列生成一个索引并用 ROW_ID 进行标识。(ROW_ID 是数据行中的一个隐藏列)
二、手动创建索引
2.1 主键索引
方法一,创建表时创建主键
方法二,创建表时单独指定主键列
create table t_test_pk1(id bigint auto_increment,name varchar(20),primary key(id)
);
方法三,修改表中的列为主键索引
① 首先只定义字段名以及字段类型,不增加任何约束:
create table t_test_pk2(id bigint,name varchar(20)
);
② 其次创建主键索引
alter table t_test_pk2 add primary key(id);alter table t_test_pk2 modify id bigint auto_increment;
2.2 唯一索引
方法一,创建表时创建唯一键
create table t_test_uk(id bigint primary key auto_increment,name varchar(20) unique
);
方法二,创建表时单独指定唯一列
create table t_test_uk1 (id bigint primary key auto_increment,name varchar(20),unique(name)
);
方法三,修改表中的列为唯一索引
create table t_test_uk2(id bigint primary key auto_increment,name varchar(20)
);alter table t_test_uk2 add unique (name);
2.3 普通索引
创建时机:
1、创建表的时候,明确哪些列是被频繁查询的,就将该列创建为索引(当表中数据过少时,全表扫描可能效率还比使用索引的效率高,因此可不创建索引);
2、随着业务的不断发展,在版本迭代的过程中添加索引。
方法一,创建表时指定索引列
create table t_test_index(id bigint primary key auto_increment,name varchar(20) unique,sno varchar(10),index(sno)
);
方法二,修改表中的列为普通索引
create table t_test_index1 (id bigint primary key auto_increment,name varchar(20),sno varchar(10)
);alter table t_test_index1 add index(sno);
方法三,使用 create index 索引名 on 表名(列名[,列名..]); 的语句创建索引,必须指定索引名
create table t_test_index2(id bigint primary key auto_increment,name varchar(20),sno varchar(10)
);create index index_name on t_test_index2(sno);
三、创建符合索引
创建语法与创建普通索引相同,只不过指定多个列,列与列之间用逗号隔开。
方法一,创建表时指定索引列
create table t_test_index4(in bigint primary key auto_increment,name varchar(20),sno varchar(10),class_id bigint,index(sno, class_id)
);
方法二,修改表中的列为符合索引
create table t_test_index5(id bigint primary key auto_increment,name varchar(20),sno varchar(10),class_id bigint
);alter table t_test_index5 add index(sno, class_id);
方法三,单独创建索引并指定索引名【推荐使用】
create table t_test_index6(id bigint primary key auto_increment,name varchar(20),sno varchar(10),class_id bigint
);create index index_name on t_test_index6 (sno, class_id);
四、查看索引
方法一:show keys from 表名;
方法二:show index from 表名;
方法三:desc 表名;
五、删除索引
5.1 删除主键索引
语法:alter table 表名 drop primary key;
示例:
自增列不能被删除,如果要删除主键,那么需要先修改主键中的自增属性:
5.2 删除其他索引
语法:alter table 表名 drop index 索引名;
六、创建索引的注意事项
索引应该创建在高频查询的列上;
索引需要占用额外的存储空间;
对表进行插入、更新和删除操作时,同时也会修改索引,可能会影响性能;
创建过多或不合理的索引会导致性能下降,需要谨慎选择和规划索引。
七、如何查看 SQL 语句走没走索引
答:可以通过使用 explain 关键词加 SQL 语句; 的语法查看执行计划。
示例:
7.1 不加条件,查询所有数据
7.2 使用主键查询
mysql> explain select * from student where id = 1;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | student | NULL | const | PRIMARY | PRIMARY | 8 | const | 1 | 100.00 | NULL |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
7.3 查询条件符合最左前缀原则(会走索引)
示例1:使用联合索引的第一列 sno
示例2:同时使用 sno 和 name(即索引的全部列)
7.4 查询条件不符合最左前缀原则(索引失效)
7.5 索引覆盖(高效使用索引)
key 列和 Extra 额外列显示的信息表示 查询需要的数据(sno 和 name)在索引树中已经全部存在,数据库无需回表查询数据行,速度极快。
总结:这类查询不仅走了索引,还实现了索引覆盖,是最高效的方式。
7.6 总结
执行 EXPLAIN + 你的SQL语句
,然后看两个关键列:
-
key
列:-
如果显示为 索引名(如
student_index
) -> 走了索引。 -
如果显示为
NULL
-> 没走索引。
-
-
Extra
列:-
如果包含
Using index
-> 实现了索引覆盖,非常高效。 -
如果包含
Using where; Using index
-> 使用了索引,但可能在索引列上做了过滤。 -
如果包含
Using filesort
或Using temporary
-> 需要优化,可能涉及排序或临时表。
-
简单来说,对于学生表:
-
WHERE sno = ...
(走索引) -
WHERE sno = ... AND name = ...
(走索引) -
SELECT sno, name FROM ...
(可能实现索引覆盖) -
WHERE name = ...
(不走student_index
索引,除非为name
单独建索引)