目录
1.MySQL如何实现索引机制
1.1InnoDb与MyISAM索引实现区别是是什么?
1.2一个表中如果没有创建索引,还会创建B+树么?
2.说一下B+树索引实现原理(数据结构)
2.1聚簇索引和非聚簇索引在B+树实现区别是什么?
2.2说一下B+树中聚簇索引的查找(匹配)逻辑
2.2说一下B+树中非聚簇索引的查找(匹配)逻辑
2.3平衡二叉树、红黑树、B树和B+树的区别是什么?都有那些应用场景?
2.4一个B+树可以存放多少数据
2.5使用B+树存储的索引crud执行效率如何?
2.6什么是自适应哈希索引?
2.7什么是2-3树和2-3-4树?
3.为什么官网建议使用自增长主键id作为索引结构(说一下自增长主键和字符串类型主键的区别和影响)
3.1使用int自增主键后,最大id是10,删除id10和9,再添加一条记录,最后添加的id是几?删除后重启mysql后子厚一条记录id是几?
4.索引的优缺点时什么?
4.1使用索引一定会提高效率么?
4.2如果是大段的文本内容,如何创建(优化)索引?
5.什么是聚簇索引
5.1一个表中可以有多个(非)聚簇索引吗?
5.2聚簇索引和非聚簇索引的区别是什么?
5.3CRUD时聚簇索引与非聚簇索引区别是什么?
5.4非聚簇索引为什么不存储数据地址而存储主键呢?
6.什么是回表操作
6.1什么是覆盖索引
6.2非聚簇索引一定要回表查询吗?
6.3为什么要回表查询?直接存储数据不可以么?
6.4如果把一个InnoDB表的主键删除,是不是就没有主键,就没办法进行回表查询了?
7.什么是联合索引、组合索引、复合索引?
7.1复合索引创建字段顺序不一样使用效果一样么?
8.什么是唯一索引?
8.1唯一索引是否影响性能?
8.2什么时候使用唯一索引?
9.什么时候创建索引,什么时候不适合创建索引?
10.什么是索引下推?
11.那些情况会导致索引失效?
11.1为什么以like=%开头会导致索引失效?
12.一个表有多个索引的时候是否能够手动指定使用那个索引?
12.1如何查看一个表的索引?
12.2能否查看索引使用的逻辑?是否使用optimizer_trace?
12.3多个索引优缺点如何匹配?
13.使用Order By时能否通过索引排序?
13.1通过索引排序内部流程是什么?
13.2是什么是双路排序?什么是单路排序?
14.如果表中有字段为null,又被经常查询该不该给这个字段创建索引?
14.1有字段为null索引是否会失效
1.MySQL如何实现索引机制
MySQL中索引分三类:B+树索引、Hash索引、全文索引
1.1InnoDb与MyISAM索引实现区别是是什么?
1.InnoDB在存储的数据是存在同一个文件里的,索引是在同一个文件进行追加一下,InnDB中也有聚簇索引和非聚簇索引,聚簇索引可以直接定位到具体数据,非聚簇索引需要根据id进行回表操作,找到对应的值。辅助索引(非主键索引、非聚簇索引)data域存储记录主键值而不是地址,数据的本身就是索引文件
2.MyISAM是数据和索引存储到不同位置,分开存储
3.索引在最叶子结点存储的具体指向id。MyISAM具体存是每一行的物理地址
MyISAM图:
1.2一个表中如果没有创建索引,还会创建B+树么?
都会创建B+树
如果有创建主键,会使用主键创建聚簇索引,如果没有规定具体主键,会有隐藏字段DB_ROW_id来当默认的b+树索引,但是不能使用。
2.说一下B+树索引实现原理(数据结构)
2.1聚簇索引和非聚簇索引在B+树实现区别是什么?
聚簇索引:
关键点(5点):
1.索引和数据存储在同一个B+树中
2.页内记录的是单向链表,
3.页与页之间也是通过主键的大小排序成一个是双向链表
4.非叶子结点存储的是主键+页号
5.非叶子结点存储的是完整数据
优点:
1.建立的索引是在B+树中,聚簇索引的查询会比非聚簇索查询效率快
2。因为建立的是从主键建立的索引,所以排序和查找速度非常快。
3.按照聚簇索引进行排序的,在查询一定范围内的数据时候,地址是相连的,数据库会从更少的数据块获取到数据,减少了磁盘的IO次数。
缺点:
1.插入速度严重依赖插入顺序,按照主键插入时最快的方式,否则会导致页分裂的情况,影响性能。所以在InnDB中通常定义一个自增的Id为书简
2.更新主键的代价特别高,所以我们一般都会定义一个自增的主键id
限制:
1.每个表结构是能有一个存储引擎,且聚簇索引只支持在InnoDB中,不支持在MyISAM且只能有一个
2.由于数据的物理存储排序方式只能有一个,所以每个MySQL的表中只能由一个聚簇索引
3.没有没有定义主键值,InnoDB会默认生成一个主键的隐性id
4.InnoDB主键选择为有序id,不建议使用无序id,比如UUID,MD%,HASH、字符串作为主键,无法保障数据的顺序增长。
非聚簇索引(二级索引):
区别:
1.是在原来的聚簇索引的B+树上重新建立一个B+树,非叶子存储的是索引关键字+页号等,叶子结点存储了索引关键字+主键id。
2.页内记录根据索引为单向链表
3.页外记录为双向链表
4.叶子存储不是一个完整的数据,存储的是索引值+主键id
2.2说一下B+树中聚簇索引的查找(匹配)逻辑
聚簇索引的查找是通过主键值进行查找,索引的存储单位是页,页内数据是聚簇索引的单链表相连,页与页之间的联系是通过主键进行双向链表进行查询。匹配过程是先通过主键找到对应的叶子结点然后进行在获取当前列的值。如果有则返回,没有则返回空值
2.2说一下B+树中非聚簇索引的查找(匹配)逻辑
跟聚簇索引的是,创建一个新的b+树,索引值会有重复,也会按照转换的ASCII码进行大小的匹配。可以加唯一约束,进行对非聚簇索引的优化。创建联合索引或者复合索引的时候需要注意索引失效的问题。
2.3平衡二叉树、红黑树、B树和B+树的区别是什么?都有那些应用场景?
平衡二叉树(存储少量数据可以):
基本数据结构
左右平衡
高度大于1会自旋
每个结点记录一份数据
红黑树(AVL):
hashmap存储
两次旋转达到平衡
分为红黑结点
B+树和B树:
B树的结点存数据
B+树存储数据全部放在叶子结点中
2.4一个B+树可以存放多少数据
默认一个page为16K(进项不修改),一般格式化之后磁盘的区块是4k大小
假设:根节点 只存主键+指针(叶子结点)+其他信息=10字节
叶子结点数据每个存储:1K大小
1600+1600*16K
2.5使用B+树存储的索引crud执行效率如何?
c:新增 O(logn*N) N表示树的高度
r:效率高
u:效率高
d:效率比较低
2.6什么是自适应哈希索引?
mysql内部提供的额外的索引机制,自动化生成,没办法手动干预,只能在InnoDb上。在高频查询之上,再生成一套索引出来。
show engine innodb status \G
2.7什么是2-3树和2-3-4树?
2-3树表示子节点下面允许存在2个或3个结点
2-3-4树
表示根节点下有两个结点,两个结点下有3个结点或者4个结点。子结点小于4个也可以,但是不能大于。
3.为什么官网建议使用自增长主键id作为索引结构(说一下自增长主键和字符串类型主键的区别和影响)
1.自增主键能维持底层数据的顺序读写(会非常快,SSD还是机械硬盘,由顺序读写的参数比如500M/B)。随机写和随机读也会导致页分裂分体
2.读取可以由b+树的二分查找定位(精确定位)
3.支持范围查找,范围数据自带顺序
3.1使用int自增主键后,最大id是10,删除id10和9,再添加一条记录,最后添加的id是几?删除后重启mysql后子厚一条记录id是几?
1.11
2.9
不重启会延续原本的id进行增加,如果重启后会更新,并按照最大id进行插入。
show create tabe 表名;会有一个auto_increment=[一个数字];这个数字表示自增id
4.索引的优缺点时什么?
优点:
聚簇(主键)索引:
1.顺序读写
2.范围快速查找
3.范围查找自带顺序
非聚簇索引:
1.避免全表扫描
2.覆盖索引可以避免回标
3.范围、排序、分组查询返回行id,分组排序后,再回表查询完整数据,有可能利用顺序读写
索引的代价:
空间上的代价:
索引是个好东西,不能乱建,,它在空间和时间上都会消耗
每建立一次索引都会创建一个B+树
时间上的代价:
每次对数据的增、删除、修改都会区修改B+树索引。而增、删、改可能会对页节点的排序造成破坏,所以存储引擎需要额外的时间进行一些记录位移,页面分裂,页面回收等操作来维护号结点和记录排序。
4.1使用索引一定会提高效率么?
1.不一定,当数据量比较小的时候,通过mysql的内部优化器处理就不会走索引
2.索引建立太多了,频繁的修改操作也会影响
3.unique唯一索引,在插入数据的时候也会先进行检测再进行插入也会影响效率,但是仍然会使用
4.2如果是大段的文本内容,如何创建(优化)索引?
1.分表存储,创建索引
2.使用es为大文本创建索引
5.什么是聚簇索引
索引和数据放在一起组合成一个b+树
5.1一个表中可以有多个(非)聚簇索引吗?
不可以,拿主键创建索引只能有一个
5.2聚簇索引和非聚簇索引的区别是什么?
在数据集额外创建的B+树
5.3CRUD时聚簇索引与非聚簇索引区别是什么?
1.聚簇索引要比非聚簇索引插入新值要慢很多,因为要保证主键不能重复
2.聚簇索引范围、排序查找效率比较高,因为是有序的
3.非聚簇索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到数据
5.4非聚簇索引为什么不存储数据地址而存储主键呢?
因为聚簇索引中又是会引发分页、重排操作,数据有可能会移动
6.什么是回表操作
假设表中有name ,age,sex字段
对age创建索引 create index idx_age on 表(age)
select * from 表 where age>10
此时通过走age的索引,然后获取主键id再进行查找
6.1什么是覆盖索引
对age和name创建了索引
select age,name from 表 where age>20 and name like '%景%'
此时就是覆盖索引
6.2非聚簇索引一定要回表查询吗?
不一定,只要b+树中包含字段(创建索引的字段),覆盖(包含)想要select字段,那么就不会回标查询
6.3为什么要回表查询?直接存储数据不可以么?
B+树比B树的优点是将数据存储移动到叶子结点中,这样就导致树比较矮和胖,查找效率高,如果树比较高那么自旋就比较高。
那么如果对数据内容修改的话,所有的辅助索引都需要修改,这就会导致大量的io
主要查询是使用id查,
6.4如果把一个InnoDB表的主键删除,是不是就没有主键,就没办法进行回表查询了?
不是,如果没有创建主键则会由一个rowid,但是用户没有办法直接使用,但是可以进行回表操作
7.什么是联合索引、组合索引、复合索引?
三个是一个东西,按照顺序创建索引。
按照不同字段,组合创建索引
全值匹配
最左前缀
7.1复合索引创建字段顺序不一样使用效果一样么?
不一样
比如创建索引的时候是A和B的复合索引
create index idx_A_B on 表(A,B)此时想要出发A和B的复合索引只能是使用A索引或者A_B索引。先用A进行排序,再用B进行排序。
创建流程是先创建一个关于A索引B+树,在此树基础上再进行对B的排序
8.什么是唯一索引?
唯一索引,索引列必须唯一,允许由Null值,且Null值可能会出现
创建方式:
创建表的时候创建
unique index uk_列(列)
额外创建:
create unique index uk_列 on 表(列)
8.1唯一索引是否影响性能?
影响性能。但是可以忽略不记
唯一特定字段,即使是多个字段组合,也必须建成唯一索引。根据墨菲定律一定会有脏数据的产生。
8.2什么时候使用唯一索引?
业务上需要由唯一特性的字段。
9.什么时候创建索引,什么时候不适合创建索引?
适合创建索引:
1.经常查询而不去修改的字段
2.where查询的字段
3.分组字段
4.排序字段
5.统计函数字段count(),Max()
不适合创建索引:
1.频繁修改的字段
2.where中没有用到的字段
3.表的数据比较少
4.mysql函数计算的列
创建索引时候会有以及啊极端影响:
1)宁缺毋滥:
认为一个查询就需要创建一个索引
2)宁滥勿缺:
觉得创建索引会影响磁盘的消耗而不创建索引
3)抵制唯一索引。认为业务的为一性一律需要再应用层通过“先查后插”的方式解决,否则并发处理,锁表开启事务
10.什么是索引下推?
目的:为了提高索引的利用率
5.6之后才有的
使用explain中出现using index condition又叫Index Condition pushdown Optimization(索引下推),可以手动关闭,但是不需要使用索引的时候还是经常使用到的。
原理:
比如在没有索引下推的时候,where name like '张%' and age
创建通过name和age这两个字段创建索引,执行顺序是第一次先走索引name,然后进行回标操作,在获取第一次的结果集后,使用age索引进行第二次查询,此时仍然需要回标进行操作。总过程进行了两次的回表操作。而索引下推就表示执行了一次回表,在第一次查询结果之上再进行查询。
总结:
未开启索引下推:
根据筛选条件再索引树中筛选第一个条件
获取结果集后进行回表操作
进行其他条件删选
再进行回表操作
开启索引下推:
在条件查询时,当前索引树如果满足全部筛选条件,可以在当前树中完成全部筛选过滤,得到比较小的结果集在进行回表操作。
11.那些情况会导致索引失效?
1.计算函数会导致索引失效,比如left
2.以like=%开头导致索引失效
3.条件判断,!= ,<>
4.is not null失效(可能不走索引)和is null()
5.类型转换会导致索引失效
6.索引没有遵循最左排序
7.数据量比较小的时候,优化器觉得不走索引比较快
11.1为什么以like=%开头会导致索引失效?
以%开头并不一定会导致索引失效
结论:在覆盖索引的时候,会走索引,type会等于index
过程:
假设3个字段:id,name,age
select * from where name='%景' 此时type=all
如果
select name from where name='%景' 此时type=index
%开发导致索引失效是因为,每一个字段通过ASCII码进行排序,假设有两个子张三,此时建立索引的B+树是先从张的ASCII建立,然后从三上在原本B+树进行维护。如果跳过开头就没有办法进行查询索引了
12.一个表有多个索引的时候是否能够手动指定使用那个索引?
不可以,内置查询优化器会自行判断使用那个索引
12.1如何查看一个表的索引?
show index from 表
explain 查询语句
12.2能否查看索引使用的逻辑?是否使用optimizer_trace?
可以,但是得先开启
#开启
set session optimizer_trace="enabled=on",end_markers_in_json=on;
#查看
SELECT * FROM information_schema.OPTIMIZER_TRACE;
#线上环境关闭
set session optimizer_trace="enabled=off";
12.3多个索引优缺点如何匹配?
(1条消息) MySQL 调优 | OPTIMIZER_TRACE详解_optimizer trace_ITMuch.com的博客-CSDN博客
可以optimizer_trace查看,如果cost(索引的使用成本)值如果,cost越低则越能被使用
索引优先级:
1.主键(唯一索引)匹配
2.全职匹配(单值匹配)
3.最左前准匹配
4.范围匹配
5.索引扫描
6.全表扫描
一般性建议:
1.对单键索引,尽量选择过滤性更好的索引(例如:手机号、邮件、身份证)
2.选择组合索引的时候,选择过滤性更好的字段排序,且越在前面越好
3.选择组合索引时,尽量包含where中更多字段的索引
4.组合索引触犯范围查询时,尽量把这个字段放在做因次序的最后面
5.尽量避免索引失效的情况
13.使用Order By时能否通过索引排序?
不能,没有过滤(where、limit),不走索引
13.1通过索引排序内部流程是什么?
首先得有过滤条件才能使用。
覆盖索引会在内存结果直接进行排序,然后进行返回。
select的字段没有完全匹配,则会进行单双路排序。跟max_length_for_sort_data
关键配置:
sort_buffer可供排序的内存缓冲区大小,
max_lenght_for_sort_data(判断能否进入内存进行排序):单行所有字段总和限制,超过这个大小启动该双路排序
1.通过索引检测过滤筛选条件到需要排序的字段+其他字段(如果符合索引)
2.判断所以内容是否覆盖select的字段
1.如果时覆盖索引,则在内存中进行排序,排序后直接返回结果
2.如果没有覆盖则会计算大小,如果超过max_lenght_for_sort_data,则直接进行双路排序,否则进行单路排序。
13.2是什么是双路排序?什么是单路排序?
单路排序:一次取出所有字段进行排序,然后内存中进行排序返回,内存不够用的时候会使用磁盘。
双路排序:从磁盘中取出排序字段进行排序,在buffer中进行排序,再从磁盘中获取其他字段,对磁盘进行两次扫描
13.3group by分组喝order by在索引使用上又什么区别?
使用上几乎一致,遵循最左匹配原则
group by使用的时候必须先进行一次排序,没有过滤条件也可以用上索引
order by必须有过滤条件才能使用上索引
14.如果表中有字段为null,又被经常查询该不该给这个字段创建索引?
创建。null其实也是数值,在查询如果为空,那么在B+树上,也都是空值
14.1有字段为null索引是否会失效
不一定会失效。每一条sql具体有没有使用索引可以通过trace追踪一下。最好还是赋予默认值,数字默认0或者null