mysql索引
后面explain介绍等级参考文档:https://blog.csdn.net/ssspk_/article/details/89422085 大道至简
要了解原理,说白了就是要明白他需要做什么,索引的目的是什么,如果是你,你会如何设计?
首先,在一个表中,存储数据过大的时候,我们如何才可以快速找到我们需要的数据?索引就像字典的目录一样,根据目录,可以很快找到内容所在的位置,进一步找到我们需要的data。
官方一点:索引是帮助MySQL高效获取数据的排好序的数据结构。
接下来开始第二步,索引要如何设计,采用哪种算法,哪种数据结构可以进一步提高速度?
数据结构:B树,B+树。
首先看下B树:

hash类型的索引:查询单条快,范围查询慢 btree类型的索引:b+树,层数越多,数据量指数级增长(innodb默认支持它)
InnoDB 支持事务,支持行级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引; MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引,不支持 Hash 索引; Memory 不支持事务,支持表级别锁定,支持 B-tree、Hash 等索引,不支持 Full-text 索引; NDB 支持事务,支持行级别锁定,支持 Hash 索引,不支持 B-tree、Full-text 等索引; Archive 不支持事务,支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引;


非主键索引存储内容:
注:frm后缀存储的表结构,ibd存储的索引和数据。第一个图最后的叶子结点存储的是索引及其所有数据。

首先类型有许多,这里我只给大家介绍企业里面用的最多的类型:
system>const>eq_ref>ref>range>index>ALL
越往左边,性能越高,比如system就比ALL类型性能要高出许多,其中system、const只是理想类型,基本达不到;
我们自己实际能优化到ref>range这两个类型,就是你自己写SQL,没优化基本上就是ALL,优化尽量达到ref>range这两个级别;
左边基本达不到!
要对type优化的前提是,你需要有索引,如果你连索引都没有创建,那你就不用优化了,肯定是ALL.....;
Type级别详解
一.system级别
索引类型能是system的只有两种情况:
1.只有一条数据的系统表
只有一条数据的系统表,就是系统里自带一张表,并且这个表就一条数据,这个基本上就达不到,这个是系统自带的表,而且就一条数据,所以基本达不到;
2.或衍生表只能有一条数据的主查询
这个是可以实现的,但是在实际开发当中,你不可能去写一个这么个玩意儿,不可能公司的业务去让你把SQL索引类型写实system...
const级别
1.仅仅能查出一条的SQL语句并且用于Primary key 或 unique索引;
能查出来一条SQL语句,你的索引还必须是Primary key或unique;
三.eq_ref级别
唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多,不能0);
解说:比如你select ...from 一张表 where 比方说有一个字段 name = 一个东西,也就是我们以name作为索引,假设我之前给name加了一个索引值,我现在根据name去查,查完后有20条数据,我就必须保证这二十条数据每行都是唯一的,不能重复不能为空!
添加唯一键语法:alter table 表名 add constraint 索引名 unique index(列名)
检查字段是否唯一键:show index form 表名;被展示出来的皆是有唯一约束的;
四 .ref级别
到ref还是问题不大的,只要你上点心,就可以达到;
非唯一性索引:对于每个索引键的查询,返回匹配的所有行(可以是0,或多个)
假设我现在要根据name查询,首先name可能有多个,因为一个公司或学校叫小明的不止一个人,但是你要用name去查,你必须name是索引,我们先给它加个索引,因为要达到ref级别,所以这里我给它加一个单值索引:
单值索引语法:alter table 表名 索引类型 索引名(字段)
五.range级别
检索指定范围的行,查找一个范围内的数据,where后面是一个范围查询 (between,in,> < >=);
注:in 有时会失效,导致为ALL;
六.index级别
查询全部索引中的数据
讲解:假设我有一张表,里面有id name age,这个时候name是一个单值索引,一旦name被设定成索引,它就会成为B树一样,经过各种算法将name里面的值像树一样进行分类,这个时候我where name = **,就相当于把这颗B树查了一个遍,
也就是说,你把name这一列给查了一遍;
SQL语句:select id From student;//我只查被索引声明的列,必然就是index了;
七.ALL级别
查询全部表数据,就是select name From student;
其中 name 不是索引;
如果你查的这一列不是索引,就会导致全表扫描,所以要避免全表扫描;