索引基础
索引是什么
索引类似一本书的目录结构,方便很快的查找、检索到书的具体内容;而MySQL的索引也是存储引擎用于快速找到记录的一种数据结构,它能够加快数据的查询速度,这是索引的基本功能;索引对于 MySQL 优化性能非常关键,尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要,在数据量较小且负载较低时,不恰当的索引对性能的影响可能并不明显,但当数据量逐渐增大时,性能则会急剧下降。
索引数据存储位置
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中,根据不同的存储引擎,索引数据可能单独存储索引文件中,也可能与数据一起存储;下面罗列下常见存储引擎 MyISAM 与 InnoDB 的数据存储格式。
| 存储引擎 | 磁盘文件存储格式 | 文件存储格式均有 |
| MyISAM | ".MYD"文件是 MyISAM 存储引擎专用,存放MyISAM表的数据 | .frm文件:无论是那种存储引擎,创建表之后都会生成一个以表命名的'.frm'文件,frm文件中主要存放与表相关的数据信息,主要包括表结构的定义信息,当数据库崩溃时,用户可以通过frm文件来恢复数据表结构。 |
| .MYI 文件是用于 MyISAM 存储引擎的,主要存放 MyISAM 表的索引信息,对于 MyISAM 存储来说,可以被缓存的内容主要来源于".MYI"文件中; | ||
| InnoDB | 根据Innodb的数据存储方式可以分为两种: 独享表空间存储数据,它使用使用".ibd"文件来存放数据,包括索引数据; 共享表空间存储数据,它使用".ibdata"文件来存放数据,所有表共享ibdata文件,包括索引数据; | |
| 涉及参数:innodb_data_home_dir 、innodb_data_file_path、 show variables like "innodb_file_per_table"; ON代表独立表空间管理,OFF代表共享表空间管理; |
索引创建原则
注意,索引并不是越多越好,虽然索引能提高数据检索效率,但是会降低更新表的效率;比如每次增删改操作,不仅要保存数据,还要保存或更新对应的索引文件;
1. 尽量使用小的数据类型的列字段;比如:能使用TINYINT类型时,不要使用INT类型。数据类型越小,所占存储空间越小,不仅能节省系统存储空间,还能提高处理效率;
2. 尽量使用简单的数据类型的列;MySQL 处理简单的数据类型比复杂的数据类型,系统开销小;
3. 尽量不要在NULL值字段上创建索引;在NULL值字段上创建索引,会使索引、索引的统计信息和比较运算更加复杂。因此可以在创建表时,在索引列中,不要使用默认值 NULL,将字段设为 NOT NULL,并赋予默认值。
索引适用场景
1. 数据表中的主键和外键;
2. 数据表中的数据达到一定的数据级,应当为数据表适当添加索引;
3. 与其它表经常进行关联查询时,应当为连接字段创建索引;
4. 作为 where 条件的判断字段,并且经常用来进行相等比较操作的字段;
5. 作为 order by 语句的字段;
6. 作为搜索一定范围内的字段,并且经常用来执行查询操作的;
7. 频繁查找的字段,select 后面的,覆盖索引;
注意:当查询数据时很少用的列或字段、某个字段包含的数据很少、数据类型的字段,如 TEXT、BLOB、BIT等数据类型的字段、当在数据表中修改数据的频率远大于查询数据频率时等,这些场景不适合创建索引,还有查询字段不会做为 where 条件或者 order by 字段时也不适合创建索引。
索引遍历方式
| MySQL数据遍历方式 | 说明 | 优点 | 缺点 |
| 顺序遍历 | 从表中第一行,顺序扫描表中的所有数据,直到在数据表中匹配到要查询的数据。 | 简单,磁盘空间占用少; | 数据量少时,无明显性能问题,随着数据量越来越大,查询性能会越来越低;百万级或者千万级表数据,查询用时往往是不可容忍的; |
| 索引遍历 | 通过遍历索引定位到数据表中的记录行; 1. 被索引的列会自动排序,包括单列索引和组合索引,这样在查询时,可以降低数据排序成本,降低了CPU的消耗; 2. 如果按照索引列的顺序进行排序,对应Order by语句来说,效率会提高很多; 3. where 索引列在存储引擎层进行处理; 4. 覆盖索引,不需要回表查询; | 1. 能够极大的提高数据检索效率,提高查询性能,降低数据库的IO成本; | 1. 索引数据本身占用一定的存储空间; |
| 2. 所有字段都可以添加索引; | 2. 索引创建、维护需要一定时间,随时数据量的不断增长,耗费的时间会越来越长; | ||
| 3. 可以添加组合索引; | 3. 对数据表中的数据进行增加、删除和修改操作时,MySQL内部需要对索引进行动态维护,这也会消耗一定时间; | ||
| 4. 提供数据分组与排序的性能 ; |
索引原理分析
索引是在存储引擎中实现的,并且不同的存储引擎会使用不同的索引,这里简单说下存储引擎是什么,存储引擎代表的是一种存储技术,对于每种存储引擎来说,其对应的存储机制、索引存放方式、索引技巧、数据库锁机制及数据的存储方式各不相同,常见存储引擎 MyISAM 和 InnoDB 存储引擎,只支持B+TREE索引。
讲到数据存储,就涉及到存储数据的大小,最小存储单位,InnoDB 存储引擎是一棵 B+ 树,它可以存放多少行数据?其实这个问题是可以计算出来,要搞清楚这个问题,需要清楚 InnoDB 索引数据结构、数据组织方式。

比如磁盘的数据存储单位是扇区,默认大小512字节,文件系统EXT4 最小单元是块,大小为4K,而我们InnoDB存储引擎的最小存储单元叫页,一个页的大小默认是16K,通过show variables like 'innodb_page_size';来查看或者自定义。
数据库中表的数据是存储在页中的,一页中能存储多少行数据呢?假设一行存储1K,那么一个页可以存入16行这样的数据,如果数据库按这种方式进行存储,查找数据就成为一个问题,因为我们不知道数据在哪个页中,此时就需要顺序遍历一遍,那样太慢了,所以人们想了一个办法,使用B+树的方式组织数据,B+树的叶子节点才会存储数据,非叶子节点不存放数据,如下图:

B+树的特点是左分支的值一定比右分支大,并且数据是存放在叶子节点中,非叶子节点存储键值+指针,如了方便介绍 InnoDB 中使用B+树,简单画了下图;

为了便于理解假设一个页中只存放 3 条记录,实际情况可以存放很多,这里有页3、4、5、6、7共5个页,是高度为2的B+树;我们先将数据记录按主键进行排序,分别存放在不同的页中,上面 page number=3的页,存放键值与指针的页,而叶子节点页 4、5、6、7页存键值与数据。
此时如果我们想查找id=5的记录,这里 id 是主键,我们通过这棵 B+ 树来查找,首先找到根页,你怎么知道数据表的根页在哪呢?其实每张表的根页位置在表空间文件中是固定的,即 page number=3 的页,找到根页后通过二分查找法,定位到 id=5 的数据应该在指针 P 指向的页中,那么进一步去 page number=5 的页中查找,同样通过二分查询法即可找到 id=5 的记录:5 k8s5 55,这样我们就很快的检索到数据了。以上就是 InnoDB 中主键索引 B+ 树是如何组织数据、查询数据的,我们总结一下:
1. InnoDB 存储引擎的最小存储单元是页,也可以用于存放数据也可以用于存放键值+指针,在 B+ 树中叶子节点存放数据,非叶子节点存放键值+指针;
2. 索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中,进而在去数据页中查找到需要的数据;
InnoDB B+树 可以存放多少行数据呢?
这里我们先假设 B+ 树高为 2,即存在一个根节点和若干个叶子节点,那么这棵 B+ 树的存放总记录数为:根节点指针数*单个叶子节点记录行数;
单个叶子节点存储记录行数:最小单位16K/1K单行数据量=16,即16行记录;
非叶子节点能存放多少指针:其实这也很好算,我们假设主键 ID 为 bigint 类型,长度为 8 字节,而指针大小在 InnoDB 源码中设置为 6 字节,这样一共 14 字节,一个页中能存放多少这样的单元,其实就代表有多少指针,即 16384/14=1170;
B+ 树高为2的话,能存放 1170*16=18720 行1K大小的数据行记录,根据同样的原理我们可以算出一个高度为 3 的 B+ 树可以存放:1170*1170*16=21902400 条这样的记录。
如何获得 InnoDB 主键索引 B+ 树的高度?
在 InnoDB 的表空间文件中,约定 page number 为 3 的代表主键索引的根页,而在根页偏移量为 64 的地方存放了该 B+ 树的 page level,而 B+ 树的高度= page level + 1;

从上图中可以验证在 InnoDB 的表空间文件中,约定 page number 为 3 的代表主键索引的根页。

page level 的值在整个文件中的偏移量为:16384*3+64=49152+64=49216,前 2 个字节中,这里student的 0100 代表 1,test表中的0000代表0,所以表student使用的B+树高为2,而test表为1;数据量都很少,现在我们向student表中,插入一定数据的数据,然后再查看B+树的高,此时B+树的高为 3,如下图。

B+树的高度,决定了数据检索的次数,也就是需要几次磁盘IO。表1的数据行数为 600 多万,B+ 树高度为 3,表2数据行数只有 15 万,B+ 树高度也为 3,可以看出尽管数据量差异较大,这两个表树的高度都是 3,换句话说这两个表通过索引查询效率并没有太大差异,因为都只需要做 3 次 IO。
MySQL InnoDB表最多可以有多少行?
1. 如果自建主键,行的多少有主键决定,比如id int(4),大约是21亿条,超过这个记录后,会有报错日志提示;
2. 如果没有主键,innoDB会会自动创建一个隐藏row_id的字段,int(6),大约是2^(6*8)=2^48次方条记录,注意这个值如果超过,会覆盖之前的数据,不会报错;
为什么 InnoDB 存储引擎不使用B树,而使用B+树?
因为 B 树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少,指针少的情况下要保存大量数据,只能增加树的高度,导致 IO 操作变多,检索效率下降,查询性能变低。
B+树在 MyISAM 与 InnoDB 存储引擎索引中的使用?
| 索引 | 特点 | 分类 |
| 非聚集索引(MyISAM) | B+树叶⼦节点只会存储数据⾏(数据⽂件)的指针,简单来说数据和索引不在⼀起,就是⾮聚集索引; ⾮聚集索引包含主键索引和辅助索引都会存储指针的值; MyISAM 中索引检索的算法为⾸先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。 | 主键索引:MyISAM 的索引⽂件仅仅保存数据记录的地址; |
| 辅助索引:在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯⼀的,⽽辅助索引的 key 可以重复。 | ||
| 聚集索引(InnoDB) | 主键索引(聚集索引)的叶⼦节点会存储数据⾏,也就是说数据和索引是在⼀起,这就是聚集索引; 辅助索引只会存储主键值; 如果没有没有主键,则使⽤唯⼀索引键⽴聚集索引;如果没有唯⼀索引,MySQL会按照⼀定规则创建聚集索引。 | 主键索引:InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会⾃动选择⼀个可以唯⼀标识数据记录的列作为主键,如果不存在这种列,则MySQL ⾃动为 InnoDB 表⽣成⼀个隐含字段作为主键,类型为⻓整形; |
| 辅助索引:辅助索引与 MyISAM 索引的不同是 InnoDB 的辅助索引 data 域存储相应记录主键的值⽽不是地址。换句话说,InnoDB 的所有辅助索引都引⽤主键作为 data 域。 |
MyISAM 非聚集索引之主键索引

数据表中,以ID为主键索引,从MyISAM 表的主键索引图中,我们可以看到,索引文件使用B+树时,在叶子节点中的data域中,保留的是数据记录的地址,如0x07 代表的是ID为17这一行数据的地址,0x6B 代表的是ID为35的这行数据;从而知道MyISAM 的索引文件仅仅保存数据记录的地址;
MyISAM 非聚集索引之辅助索引

数据表中以 age 为辅助索引或者叫次要索引,其实他们在MyISAM存储引擎中,在存储数据的结构上没有任何区别,只是主键索引要求key值唯一,而辅助索引中的key值可以重复,从上图中,可以看到,也是B+树的形式进行保存,索引是age列,而B+树的叶子节点中的data域,也是保存的记录的地址。
InnoDB 聚集索引之主键索引

Innodb的数据表,必须要有一个可以唯一标识数据记录的列作为主键,如果创建表时,没有人为定义,InnoDB存储引擎会生成一个隐含字段作为主键,上图中我们心ID为主键,在B+树中的叶子节点中,其实他记录的是完整的行记录。因为InnoDB的数据文件本身就是按主键聚集的,也是为什么当没有主键时,InnoDB会自动的为表创建隐含主键。
InnoDB 聚集索引之辅助索引

假这里定义了 name 为辅助索引,B+树的叶子节点中的data域,它存储的是相应记录的主键的值,而不是地址,换句话说,InnoDB的所有辅助索引都引用主键值作为data域,当它检索数据时,如果是select * from user where name='Mark'; 它会根据定义的索引B+树,进行二分查找,查找到Mark后,从数据域中读取到主键的地址,然后再回到主键索引,再次根据主键索引的B+树,进行二分查找,找到对应的主键所在的叶子节点,然后再取出所有的数据,这种操作叫做回表查询,需要进行检索两次:非主键索引----> 从非主键索引的data域中获取主键ID---->再次检索主键索引的B+树---->从主键索引的叶子节点中获取到主键ID----->最终获取到数据;
如果是检索 select id,name form user where user='Mark'; 根据where条件中的name进行检索,由于name是非主键索引,按B+树进行二分查找,查找到Mark,然后再根据data域的主键ID,但这里要查询的数据是id和name,id正好是主键,在非主键索引中的叶子节点中的数据域中,保存的是主键ID,此时的查询称为覆盖索引查询。从而可以知道MySQL使用组合索引的话,可以更高效的检索数据。在实际工作中,可以根据检索的内容尽可能多的使用组合索引,形成覆盖索引,减少回表查询,减少IO次数,提高效率。
一颗B+树上面创建组合索引,省空间,更容易实现覆盖索引,组合索引,遵循最左前缀原则:
1. 前缀索引 where name like a% 可以用到索引,但如果 where name like %a,这样不可以用到索引;
2. 从左到右直到遇到范围查询检索时,> < between like,遇到这些条件时,检索将不会使用索引了。例如建⽴组合索引 (a,b,c,d),where a=1 and b=1 and c>3 and d=1;到c>3停⽌了 所以d ⽤不到索引了,如果还想使用怎么办?建立索引时使用(a,b,d,c),再使用where a=1 and b=1 and c>3 and d=1; 查询优化器,它是根据索引建立的顺序进行索引的。
索引分类及使用
| 索引分类 | 创建表时 | 已有数据表创建 | 说明 |
| 普通索引 | create table 表名( ... INDEX 索引名(列名) ); | ALTER TABLE table_name ADD INDEX index_name (column(length)) ; CREATE INDEX index_name ON table(column(length)) ; | 允许字段值重复,或者为空值; |
| 唯一索引 | create table 表名( ... UNIQUE INDEX 索引名(列名) ); | ALTER TABLE table_name ADD UNIQUE INDEX index_name(column(length)); CREATE UNIQUE INDEX index_name ON table(column(length)) ; | 索引列中的值必须是唯一的,但允许为空值; |
| 主键索引 | create table 表名( ... PRIMARY KEY (列名) ); | ALTER TABLE table_name ADD PRIMARY KEY (id); | 是一种特殊的唯一索引,不允许为空值; |
| 组合索引 | create table 表名( ... INDEX 索引名(列名1,列名2...) ); | ALTER TABLE table_name ADD INDEX index_name (column1(length),column2(length)) ; | 在多个字段组合上面创建索引,组合索引遵循最左前缀原则,一般情况下建议使用组合索引代替单列索引(主键索引除外); |
| 全文索引 | create table 表名( ... FULLTEXT INDEX 索引名(列名) ); | ALTER TABLE table_name add FULLTEXT index_name(column(length)); CREATE FULLTEXT INDEX index_name ON table(column(length)) ; | 只在MyISAM、InnoDB(5.6)引擎上才能使用,并且只能在CHAR、VARCHAR、TEXT类型字段上使用全文索引; |
| 空间索引 | create table 表名( ... SPATIAL INDEX 索引名(列名) ); | ALTER TABLE table_name ADD SPATIAL INDEX index_name(column(length)); CREATE SPATIAL INDEX index_name ON table(column(length)) ; | 空间索引,一般使用不到; |
| 降序索引 | create table 表名( ... INDEX 索引名(列名 asc, 列名 desc) ); | MySQL 8.x 真正支持降序索引,并且只有InnoDB 存储引擎支持,通过show create table 查看 | |
| 隐藏索引 | CREATE INDEX index_name ON table(column(length)) INVISIBLE ; | MySQL 8.x 开始支持隐藏索引,隐藏索引不会被优化器使用,但仍然需要维护,隐藏索引通常会在软删除和灰度发布的场景中使用。 | |
| 函数索引 | CREATE INDEX index_name ON table((函数名(字段))); | 从MySQL 8.0.13 版本开始支持在索引中使用函数或者表达式的值 ,也就是索引中可以包含函数或者表达式。 |
删除索引:DROP INDEX index_name on table_name;
查看索引:SHOW INDEX FROM table_name \G;
索引失效

构造索引失效用例;

使用explain查查执行计划;

没有使用索引时type为all,后面会详细分析各种type;

从左到右,当遇到到范围查询时> < between like,索引就失效停止了;我们知道当key_len=20时,全值匹配,效率最高,如果我们想提高效率的话,可以调整索引顺序;

调整索引顺序;

再次查询,已经使用了全值索引,这样通过调整索引的顺序,可以提高检索效率;
索引执行计划
MySQL 提供了⼀个 EXPLAIN 命令, 它可以对 SELECT 语句的执⾏计划进⾏分析, 并输出 SELECT 执⾏的详细信息, 以供开发⼈员或DBA同学对性能进行优化,使⽤ explain 这个命令来查看⼀个这些SQL语句的执⾏计划,查看该SQL语句有没有使⽤上了索引,有没有做全表扫描,这都可以通过 explain 命令来查看。可以通过 explain 命令深⼊了解 MySQL 的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运⾏SQL语句时哪种策略预计会被优化器采⽤。EXPLAIN 命令⽤法⼗分简单, 在 SELECT 语句前加上 explain 就可以了, 例如:

explain字段详解,即上面标示的1到12字段详解。
| 字段 | 字段说明 |
| id | 每个 select 语句都会自动分配的一个唯一标识符,id相同,执行顺序从上到下,id不同,id越大,优先级越高,id列为null就表示这是一个结果集,不需要使用它来查询; |
| select_type | 查询类型,主要⽤于区别普通查询、联合查询(union、union all)、⼦查询等复杂查询; |
| table | 表名显示的查询表名,如果查询使⽤了别名,那么这⾥显示的是别名,如果不涉及对数据表的操作,那么这显示为null,如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执⾏计划中的id,表示结果来⾃于这个查询产⽣。如果是尖括号括起来的<union M,N>,与类似,也是⼀个临时表,表示这个结果来⾃于union查询的id为M,N的结果集; |
| type | 依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以⽤到⼀个索引,如果类型是all,你就会发现没有使用索引了,一般来讲索引要使用range级别以上的,就已经不错了,index一般来讲是覆盖索引,用到index,只能保证不回表,在一颗索引树上查; |
| possible_keys | 检索中可能使用到的索引,一个或多个; |
| key | 查询真正使⽤到的索引,select_type为index_merge时,这⾥可能出现两个以上的索引,其他的select_type这⾥只会出现⼀个。实际使用到的索引key; |
| key_len | ⽤于处理查询的索引⻓度,如果是单列索引,那就整个索引⻓度算进去,如果是多列索引,那么查询不⼀定都能使⽤到所有的列,具体使⽤到了多少个列的索引,这⾥就会计算进去,没有使⽤到的列,这⾥不会计算进去。 留意下这个列的值,算⼀下你的多列索引总⻓度就知道有没有使⽤到所有的列了。另外,key_len只计算where条件⽤到的索引⻓度,⽽排序和分组就算⽤到了索引,也不会计算到key_len中; |
| ref | 如果是使⽤的常数等值查询,这⾥会显示const,如果是条件使⽤了表达式或者函数,或者条件列发⽣了内部隐式转换,这⾥可能显示为func; |
| rows | 这⾥是执⾏计划中估算的扫描⾏数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB⾥⾯使⽤了MVCC并发机制); |
| extra | 这个列包含不适合在其他列中显示单⼗分重要的额外的信息,这个列可以显示的信息⾮常多,有⼏⼗种; |
以上是索引执行计划字段的含义,后面会详细介绍select_type、type和extra字段,里面又涉及到很多属性信息。
索引执行计划用例

| select_type | 含义 |
| simple | 普通查询; |
| primary | 如果你有子查询或者联合查询,那么外层的这个叫promary查询,你里面的叫subquery; |
| subquery | 除了from子句中包含的子查询外,其它地方出现的子查询都可能是subquery; |
| dependent subquery | 表示这个subquery的查询要受到外部表查询的影响,这个子查询的值取决于外部表的结果; |
| union | 连接的两个select查询,第⼀个查询是PRIMARY,除了第⼀个表外,第⼆个以后的表select_type都是union,并且ID是NULL,表示是一个结果集,它的类型 为UNION_RESULT; |
| dependent union | 与union⼀样,出现在union 或union all语句中,但是这个查询要受到外部查询的影响; |
| union result | 两个select 查询拼接在一起的结果集,这种类型id为null; |
| derived | from子句中出现子查询,也叫做派⽣表或者虚表,这种select_type叫做derived类型; |
simple 用例

primary 用例

subquery用例

dependent subquery 用例

uNION用例

DEPENDENT UNION用例

| 常见type | 说明 |
| system | 表中只有一行数据或者空表; |
| const | 常量级查询,使⽤唯⼀索引或者主键,返回记录⼀定是1⾏记录的等值where条件时,通常type是const。其他数据库也叫做唯⼀索引扫描; |
| eq_ref | 一定存在关联,并且关联字段是主键或者唯⼀键,此类型通常出现在多表的 join 查询, 表示对于前表的每⼀个结果, 都只能匹配到后表的⼀⾏结果. 并且查询的⽐较操作通常是 '=', 查询效率较⾼; |
| ref | 针对⾮唯⼀性索引,使⽤等值(=)查询⾮主键。或者是使⽤了最左前缀规则索引的查询; |
| fulltext | 全⽂索引检索,要注意,全⽂索引的优先级很⾼,若全⽂索引和普通索引同时存在时,mysql不管代价,优先选择使⽤全⽂索引; |
| ref_or_null | 与ref⽅法类似,只是增加了null值的⽐较。实际⽤的不多; |
| unique_subquery | ⽤于where中的in形式⼦查询,⼦查询返回不重复值唯⼀值; |
| index_subquery | ⽤于in形式⼦查询使⽤到了辅助索引或者in 以使⽤索引将⼦查询去重; |
| range | 索引范围扫描,常⻅于使⽤>,<,is null,between ,in ,like等运算符的查询中; |
| index_merge | 表示查询使⽤了两个以上的索引,最后取交集或者并集,常⻅and ,or的条件使⽤了不同的索引,官⽅排序这个在ref_or_null之后,但是实际上由于要读取所个索引,性能可能⼤部分时间都不如range; |
| index | 条件是出现在索引树中的节点,可能没有完全匹配索引,索引全表扫描,把索引从头到尾扫⼀遍,常⻅于使⽤索引列就可以处理不需要读取数据⽂件的查询、可以使⽤索引排序或者分组的查询; |
| all | 全表扫描,是在server层进⾏过滤返回符合要求的记录; |
const用例

eq_ref用例

ref 用例

fulltext用例

range用例

index 用例

ALL 用例

| Extra常用信息 | 说明 |
| using temporary | 使用了临时表存储中间结果; |
| no tables used | 不带from子句查询; |
| using fifilesort | 文件排序,排序时⽆法使⽤到索引时,就会出现这个。常⻅于order by和group by语句中,说明MySQL会使⽤⼀个外部的索引排序,⽽不是按照索引顺序进⾏读取。MySQL中⽆法利⽤索引完成的排序操作称为"⽂件排序"; |
| using index | 覆盖索引,查询时不需要回表查询,直接通过索引就可以获取查询的数据。表示相应的SELECT查询中使⽤到了覆盖索引(Covering Index),避免访问表的数据⾏,效率不错!如果同时出现Using Where ,说明索引被⽤来执⾏查找索引键值,如果没有同时出现Using Where ,表明索引⽤来读取数据⽽⾮执⾏查找动作; |
| using where | 效率低,索引效果差,表示存储引擎返回的记录并不是所有的都满⾜查询条件,需要在server层进⾏过滤; |
| using index condition | 索引下推,5.6之后才支持,它一定用到索引了,把这个索引条件,下推到存储引擎层去检索;查询条件中分为限制条件和检查条件,5.6之前,存储引擎只能根据限制条件扫描数据并返回,然后server层根据检查条件进⾏过滤再返回真正符合查询的数据;5.6.x之后⽀持ICP特性,可以把检查条件也下推到存储引擎层,不符合检查条件和限制条件的数据,直接不读取,这样就⼤⼤减少了存储引擎扫描的记录数量,extra列显示using index condition; |
using temporary 用例

using fifilesort 用例

using index 用例

using where 用例

总结
详细总结了MySQL 存储、B+树、索引创建过程、索引执行计算、回表检索、覆盖检索、以及常见问题。
您的关注是我写作的动力
文章推荐
讲讲 tcp_tw_recycle,tcp_tw_reuse
基础小知识
专辑分享
kubeadm使用外部etcd部署kubernetes v1.17.3 高可用集群





