一. 索引简介
1. 什么是索引
索引是排序好的快速查找的数据结构,用来帮助MySQL高效获取需要的数据结果。索引会影响到MySQL查找(WHERE的查询条件)和排序(ORDER BY)两大功能!理解索引工作的方式最好的办法就是把索引比喻成书的目录,当需要查看特定的章节时通过查看目录的方式往往要比查看整个书的内容要有效很多。
补充:
(1). 除了数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。
(2). 一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。
2. 索引的分类
我们平时所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种数据结构的索引之外,还有哈希索引(Hash Index)等。
A. 分类1
单值索引:一个索引只包含单个列,一个表可以有多个单列索引。
唯一索引:索引列的值必须唯一,但是允许空值。
复合索引:一个索引包含多个字段。
B. 分类2
覆盖索引:就是select的数据列只用从索引的key中就能够获取,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
C. 分类3
聚集索引(也叫主键索引):通过主键创建的索引叫做主键索引,也叫聚集索引。
辅助索引(非聚集索引):除了主键索引以外的其它索引。
3. 索引的优缺点
A. 优点:
查找:类似大学图书馆的书目索引,提高数据检索的效率,降低数据库的IO成本。
(2) 排序:通过索引対数据进行排序,降低数据排序的成本,降低了CPU的消耗。
(3) 帮助服务器避免排序和临时表。
(4) 可以将随机IO变成顺序IO。
B. 缺点:
(1) 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。(详见下一节B+Tree结构)
(2) 虽然索引大大提高了查询速度,但是同时会降低表的更新速度,例如对表频繁的进行 INSERT 、UPDATE 和 DELETE 。因为更新表的时候,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加的索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
(3) 索引只是提高效率的一个因素,如果MySQL有大数据量的表,就需要花时间研究建立最优秀的索引。
4. 相关SQL语句
-----索引相关语句 --1. 查询索引 show index from TableName; --如:查看article表的索引 show index from article; --2. 删除索引 DROP INDEX [indexName] ON TableName; --如:删除acticle表上的 idx_article_cv 索引 drop index idx_article_cv on article; --3. 创建索引 CREATE [UNIQUE] INDEX indexName ON TableName(columnName(length)); --如:在article表上创建category_id的单个索引,名为:idx_article_c CREATE INDEX idx_article_c ON article(category_id); --如:在article表上创建category_id,views的联合索引,名为:idx_article_cv CREATE INDEX idx_article_cv ON article(category_id,views); ---ALTER相关用法 /* 1、该语句添加一个主键,这意味着索引值必须是唯一的,并且不能为NULL */ ALTER TABLE TableName ADD PRIMARY KEY(column_list); /* 2、该语句创建索引的键值必须是唯一的(除了NULL之外,NULL可能会出现多次) */ ALTER TABLE TableName ADD UNIQUE indexName(column_list); /* 3、该语句创建普通索引,索引值可以出现多次 */ ALTER TABLE TableName ADD INDEX indexName(column_list); --如:在article表中对views列添加索引,名为idx_article_v alter table article add index idx_article_v(views); /* 4、该语句指定了索引为FULLTEXT,用于全文检索 */ ALTER TABLE TableName ADD FULLTEXT indexName(column_list);
二. 执行计划
1. 什么是执行计划?
SQL的执行计划,使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理SQL语句的,explain语句对select,delete,update,insert,replace语句有效。
补充explain的两个变种(了解即可):
(1). explain extended:会在 explain 的基础上额外提供一些查询优化的信息。紧随其后通 过 show warnings 命令可以得到优化后的查询语句,从而看出优化器优化了什么。额外还有 filtered 列,是一个半分比的值,rows * filtered/100 可以估算出将要和 explain 中前一个表 进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)。
(2). explain partitions:相比 explain 多了个 partitions 字段,如果查询是基于分区表的话,会显示查询将访问的分区。
数据准备:
--数据准备 use IndexTestDB; --1. actor表 DROP TABLE IF EXISTS `actor`; create table `actor`( `id` int(11) NOT NULL, `name` varchar(45) DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE= INNODB DEFAULT CHARSET=utf8; insert into `actor`(`id`,`name`,`update_time`) values(1,'a','2020-12-22 15:27:18'),(2,'b','2020-12-22 15:27:18'),(3,'c','2020-12-22 15:27:18'); --2.film表 DROP TABLE IF EXISTS `film`; create table `film`( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name` (`name`) ) ENGINE= INNODB DEFAULT CHARSET=utf8; insert into `film`(`id`,`name`) values(1,'file1'),(2,'file3'),(3,'file3'); --3. file_actor表 DROP TABLE IF EXISTS `film_actor`; create table `film_actor`( `id` int(11) NOT NULL, `film_id` int(11) NOT NULL, `actor_id` int(11) NOT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_film_actor_id` (`film_id`,`actor_id`) ) ENGINE= INNODB DEFAULT CHARSET=utf8; insert into `film_actor`(`id`,`film_id`,`actor_id`) values(1,1,1),(2,1,2),(3,2,1);