一、索引概述
MySQL
官方对索引的定义为: 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
简单来说:在众多数据的情况下,就像书本目录一样能高效的定位查出数据。
示意图:
索引基于B+树的数据结构,每个节点都对应着每个表的指定数据。
二、索引的优势与劣势对比
优势:
- 能够类似于书本的目录索引,提高了数据的检索效率,降低数据库的IO成本。
- 能够通过索引精确对数据进行排序,降低了数据排序的成本,降低CPU的消耗
- 唯一索引还能保证每一列的数据一致性。
劣势:
- 索引增加了查询效率,但是也降低了对增删改的速度。MySQL不仅需要保存数据,还需要保存索引文件信息,需要调整和更新变化后的索引信息。
- 索引也是一张表,保存了主键和索引字段,指向了实体类记录,还需要占用空间。
三、索引结构
索引是在MySQL的存储引擎层中实现的,而不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,也不是所有的存储引擎都支持所有的索引类型的。MySQL目前提供了以下4种索引:
BTREE 索引
: 最常见的索引类型,大部分索引都支持 B 树索引。HASH 索引
:只有Memory引擎支持 , 使用场景简单 。R-tree 索引
(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少,不做特别介绍。Full-text (全文索引)
:全文索引也是MyISAM的一个特殊索引类型,主要用于全文索引,InnoDB从Mysql5.6版本开始支持全文索引。
MyISAM、InnoDB、Memory三种存储引擎对各种索引类型的支持:
索引 | InnoDB引擎 | MyISAM引擎 | Memory引擎 |
---|---|---|---|
BTREE索引 | 支持 | 支持 | 支持 |
HASH索引 | 不支持 | 不支持 | 支持 |
R-TREE索引 | 不支持 | 支持 | 不支持 |
Full-Text全文索引 | 5.6版本后支持 | 支持 | 不支持 |
我们所常用的索引一般都是基于B+树。
四、索引设计原则
索引的设计,需要与当前业务结合,需要考虑一些规则,使得索引使用效率更高效。
- 对查询频次较高,且数据量比较大的表建立索引。
- 索引字段的选择,最佳候选列应当从where子句的条件中提取,如果where子句中的组合比较多,那么应当挑选最常用、过滤效果最好的列的组合。
- 使用唯一索引,区分度越高,使用索引的效率越高。
- 索引可以有效的提升查询数据的效率,但是索引不是越多越好。对于增删改等DML操作比较频繁的表来说,索引过多,会引入相当高的维护代价,降低DML操作的效率,增加相应操作的时间消耗。另外索引过多的话,MySQL将提高选择的代价。
- 使用短索引,索引创建之后也是使用硬盘来存储的,因此提升索引访问的I/O效率,也可以提升总体的访问效率。
- 利用最左前缀,N个列组合而成的组合索引,那么相当于是创建了N个索引,如果查询时where子句中使用了组成该索引的前几个字段,那么这条查询SQL可以利用组合索引来提升查询效率。
五、MySQL使用索引
5.1、索引分类
- 单值索引 :即一个索引只包含单个列,一个表可以有多个单列索引
- 唯一索引:索引列的值必须唯一,但允许有空值
- 复合索引 :即一个索引包含多个列
5.2、索引语法
环境搭建:
CREATE TABLE `city` (
`city_id` int(11) NOT NULL AUTO_INCREMENT,
`city_name` varchar(50) NOT NULL,
`country_id` int(11) NOT NULL,
PRIMARY KEY (`city_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `country` (
`country_id` int(11) NOT NULL AUTO_INCREMENT,
`country_name` varchar(100) NOT NULL,
PRIMARY KEY (`country_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `city` (`city_id`, `city_name`, `country_id`) values(1,'西安',1);
insert into `city` (`city_id`, `city_name`, `country_id`) values(2,'NewYork',2);
insert into `city` (`city_id`, `city_name`, `country_id`) values(3,'北京',1);
insert into `city` (`city_id`, `city_name`, `country_id`) values(4,'上海',1);
insert into `country` (`country_id`, `country_name`) values(1,'China');
insert into `country` (`country_id`, `country_name`) values(2,'America');
insert into `country` (`country_id`, `country_name`) values(3,'Japan');
insert into `country` (`country_id`, `country_name`) values(4,'UK');
创建索引:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[USING index_type]
ON tbl_name(index_col_name,...)
index_col_name : column_name[(length)][ASC | DESC]
示例:为city
表中创建city_name
字段索引
create index idx_city_nmae on city(city_name);
结果:
查看索引:
show index from table_name;
示例:
删除索引:
drop index index_name on tal_name;
示例:
alter命令:
1). alter table tb_name add primary key(column_list);
该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
2). alter table tb_name add unique index_name(column_list);
这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)
3). alter table tb_name add index index_name(column_list);
添加普通索引, 索引值可以出现多次。
4). alter table tb_name add fulltext index_name(column_list);
该语句指定了索引为FULLTEXT, 用于全文索引
以上就是一些索引的使用方法。
六、MySQL的B+Tree
B+树介绍: b+树图文详解
MySql索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。
示意图:
链表加入使得左右相邻的数据更为容易查找,增加了查询的速度。