共计 4572 个字符,预计需要花费 12 分钟才能阅读完成。
置信很多人对于 MySQL 的索引都不生疏,索引 (Index) 是帮忙 MySQL 高效获取数据的数据结构。
因为索引是 MySQL 中比拟重点的常识,置信很多人都有肯定的理解,尤其是在面试中呈现的频率特地高。楼主自认为本人对 MySQL 的索引相干常识有很多理解,而且因为最近在找工作面试,所以独自温习了很多对于索引的常识。
然而,我还是图样图森破,直到我被阿里的面试官虐过之后我才晓得,本人在索引方面的常识,只是个小学生程度。
以下,是我总结的一次阿里面试中对于索引无关的问题以及知识点。
truncate 和 delete 的区别
- DELETE 是逻辑性的删除,逐行进行删除,该操作只会开释逻辑空间,能够被笼罩然而不会开释在磁盘上的物理空间属于逻辑性的删除,自增 id 会有缝隙,会有磁盘碎片产生。
- TRUNCATE table stu 对表段中的数据页进行清空,会删除表申请的数据页,开释物理磁盘空间,不会删除表定义(全表内容删除最好应用 TRUNCATE,速度比 DELETE 快)
- DROP 也是物理性的删除,会删除表定义和数据
索引概念、索引模型
咱们是怎么聊到索引的呢,是因为我提到咱们的业务量比拟大,每天大略有几百万的新数据生成,于是有了以下对话:
面试官:你们每天这么大的数据量,都是保留在关系型数据库中吗?
我:是的,咱们线上应用的是 MySQL 数据库
面试官:每天几百万数据,一个月就是几千万了,那你们有没有对于查问做一些优化呢?
我:咱们在数据库中创立了一些索引(我当初十分悔恨我过后说了这句话)。
这里能够看到,阿里的面试官并不会像有一些公司一样拿着题库一道一道的问,而是会依据面试者做过的事件以及面试过程中的一些内容进行开展。
面试官:那你能说说什么是索引吗?
我:(这道题必定难不住我啊)索引其实是一种数据结构,可能帮忙咱们疾速的检索数据库中的数据。
面试官:那么索引具体采纳的哪种数据结构呢?
我:(这道题我也背过)常见的 MySQL 次要有两种构造:Hash 索引和 B + Tree 索引,咱们应用的是 InnoDB 引擎,默认的是 B + 树。
这里我耍了一个小心机,特意说了一下索引和存储引擎无关。心愿面试官能够问我一些对于存储引擎的问题。
面试官:既然你提到 InnoDB 应用的 B + Tree 的索引模型,那么你晓得为什么采纳 B + 树吗?这和 Hash 索引比拟起来有什么优缺点吗?
我:(忽然感觉这道题有点难,然而我还是凭借着本人的常识储备简略的答复上一些)因为 Hash 索引底层是哈希表,哈希表是一种以 key-value 存储数据的构造,所以多个数据在存储关系上是齐全没有任何程序关系的,所以,对于区间查问是无奈间接通过索引查问的,就须要全表扫描。所以,哈希索引只实用于等值查问的场景。而 B + Tree 是一种多路均衡查问树,所以他的节点是人造有序的(左子节点小于父节点、父节点小于右子节点),所以对于范畴查问的时候不须要做全表扫描。
面试官:除了下面这个范畴查问的,你还能说出其余的一些区别吗?
我:(这个题我答复的不好,预先百度了一下)
科普工夫:B+ Tree 索引和 Hash 索引区别 哈希索引适宜等值查问,然而无奈进行范畴查问 哈希索引没方法利用索引实现排序 哈希索引不反对多列联结索引的最左匹配规定 如果有大量反复键值得状况下,哈希索引的效率会很低,因为存在哈希碰撞问题
聚簇索引、笼罩索引
面试官:刚刚咱们聊到 B + Tree,那你晓得 B + Tree 的叶子节点都能够存哪些货色吗?
我:InnoDB 的 B + Tree 可能存储的是整行数据,也有可能是主键的值。
面试官:那这两者有什么区别吗?
我:(当他问我叶子节点的时候,其实我就猜到他可能要问我聚簇索引和非聚簇索引了)在 InnoDB 里,索引 B + Tree 的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引。而索引 B + Tree 的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引。
面试官:那么,聚簇索引和非聚簇索引,在查问数据的时候有区别吗?
我:聚簇索引查问会更快?
面试官:为什么呢?
我:因为主键索引树的叶子节点间接就是咱们要查问的整行数据了。而非主键索引的叶子节点是主键的值,查到主键的值当前,还须要再通过主键的值再进行一次查问。
面试官:刚刚你提到主键索引查问只会查一次,而非主键索引须要回表查问屡次。(起初我才晓得,原来这个过程叫做回表)是所有状况都是这样的吗?非主键索引肯定会查问屡次吗?
我:(额、这个问题我答复的不好,起初我本人查资料才晓得,通过笼罩索引也能够只查问一次)
科普工夫——笼罩索引 笼罩索引(covering index)指一个查问语句的执行只用从索引中就可能获得,不用从数据表中读取。也能够称之为实现了索引笼罩。当一条查问语句合乎笼罩索引条件时,MySQL 只须要通过索引就能够返回查问所须要的数据,这样防止了查到索引后再返回表操作,缩小 I / O 提高效率。如,表 covering_index_sample 中有一个一般索引 idx_key1_key2(key1,key2)。当咱们通过 SQL 语句:select key2 from covering_index_sample where key1 =‘keytest’; 的时候,就能够通过笼罩索引查问,无需回表。
联结索引、最左前缀匹配
面试官:不晓得的话没关系,想问一下,你们在创立索引的时候都会思考哪些因素呢?
我:咱们个别对于查问概率比拟高,常常作为 where 条件的字段设置索引
面试官:那你们有用过联结索引吗?
我:用过呀,咱们有对一些表中创立过联结索引。
面试官:那你们在创立联结索引的时候,须要做联结索引多个字段之间程序你们是如何抉择的呢?
我:咱们把辨认度最高的字段放到最后面。
面试官:为什么这么做呢?
我:(这个问题有点把我问蒙了,略微有些慌乱)这样的话可能命中率会高一点吧。。。
面试官:那你晓得最左前缀匹配吗?
我:(我忽然想起来原来面试官是想问这个,怪本人刚刚为什么就没想到这个呢。)哦哦哦。您刚刚问的是这个意思啊,在创立多列索引时,咱们依据业务需要,where 子句中应用最频繁的一列放在最右边,因为 MySQL 索引查问会遵循最左前缀匹配的准则,即最左优先,在检索数据时从联结索引的最右边开始匹配。所以当咱们创立一个联结索引的时候,如 (key1,key2,key3),相当于创立了(key1)、(key1,key2) 和(key1,key2,key3)三个索引,这就是最左匹配准则。
尽管我一开始有点懵,没有联想到最左前缀匹配,然而面试官还是疏导了我。很友善。
索引下推、查问优化
面试官:你们线上用的 MySQL 是哪个版本啊呢?
我:咱们 MySQL 是 5.7
面试官:那你晓得在 MySQL 5.6 中,对索引做了哪些优化吗?
我:不好意思,这个我没有去理解过。(预先我查了一下,有一个比拟重要的:Index Condition Pushdown Optimization)
科普工夫—— Index Condition Pushdown(索引下推) MySQL 5.6 引入了索引下推优化,默认开启,应用 SET optimizer_switch =‘index_condition_pushdown=off’; 能够将其敞开。官网文档中给的例子和解释如下:people 表中(zipcode,lastname,firstname)形成一个索引
SELECT * FROM people WHERE zipcode=‘95054’AND lastname LIKE‘%etrunia%’AND address LIKE‘%Main Street%’;
如果没有应用索引下推技术,则 MySQL 会通过 zipcode=’95054’从存储引擎中查问对应的数据,返回到 MySQL 服务端,而后 MySQL 服务端基于 lastname LIKE ‘%etrunia%’ 和 address LIKE ‘%Main Street%’ 来判断数据是否符合条件。如果应用了索引下推技术,则 MYSQL 首先会返回合乎 zipcode=’95054’的索引,而后依据 lastname LIKE ‘%etrunia%’ 筛选出符合条件的索引后再返回到 MySQL 服务端,而后 MySQL 服务端基于 address LIKE ‘%Main Street%’ 来判断数据是否符合条件,这样返回给 MySQL 服务端的索引数又会缩小。有了索引下推优化,能够在有 like 条件查问的状况下,缩小回表次数。
面试官:你们创立的那么多索引,到底有没有失效,或者说你们的 SQL 语句有没有应用索引查问你们有统计过吗?
我:这个还没有统计过,除非遇到慢 SQL 的时候咱们才会去排查
面试官:那排查的时候,有什么伎俩能够晓得有没有走索引查问呢?
我:能够通过 explain 查看 sql 语句的执行打算,通过执行打算来剖析索引应用状况
面试官:那什么状况下会产生明明创立了索引,然而执行的时候并没有通过索引呢?
我:(依稀记得和优化器无关,然而这个问题并没有答复好)
科普工夫——查问优化器 一条 SQL 语句的查问,能够有不同的执行计划,至于最终抉择哪种计划,须要通过优化器进行抉择,抉择执行老本最低的计划。在一条单表查问语句真正执行之前,MySQL 的查问优化器会找出执行该语句所有可能应用的计划,比照之后找出老本最低的计划。这个老本最低的计划就是所谓的执行打算。优化过程大抵如下:1、依据搜寻条件,找出所有可能应用的索引 2、计算全表扫描的代价 3、计算应用不同索引执行查问的代价 4、比照各种执行计划的代价,找出老本最低的那一个
面试官:哦,索引无关的常识咱们临时就问这么多吧。你们线上数据的事务隔离级别是什么呀?
我:(前面对于事务隔离级别的问题了,就不开展了)
感觉是因为我答复的不够好,如果这几个索引问题我都会的话,他还会诘问更多,恐怕会被虐的更惨
总结 & 感悟
以上,就是一次面试中对于索引局部常识的问题以及我整顿的答案。感觉这次面试过程中对于索引的常识,本人大略可能答复的内容占 70% 左右,然而自信齐全答对的内容只占 50% 左右,看来本人索引无关的常识理解的还是不够多。
通过这次面试,发现像阿里这种大厂对于底层常识还是比拟看重的,我以前认为对于索引最多也就问一下 Hash 和 B + 有什么区别,没想到最初都能问到查问优化器下面。
最初,不论本次面试能不能通过,都非常感谢有这样一次机会,能够让本人看到本人的有余。通过这次面试,我也播种了很多货色。加油!
———————
2019 年 7 月 12 日 15:01:45 更新,应评论要求,简略整顿下事务隔离级别的常识如下,理解更多请查阅相干材料。
谈到事务最先想到的就是 ACID 属性(Atomicity 原子性、Consistency 一致性、Isolation 隔离性、Durability 持久性),明天次要介绍一下 MySQL 的隔离属性。
MySQL 的事务的隔离级别分为:未提交读(read uncommitted)、已提交读(read committed)、可反复读(repeatable read)、串行化(serializable)。未提交读:一个事务能够读取到,另外一个事务尚未提交的变更。
已提交读:一个事务提交后,其变更才会被另一个事务读取到。
可反复读:在一个事务执行的过程中所读取到的数据,和事务启动时所看到的统一。
串行化:当操作一行数据时,读写别离都会加锁。当呈现读写锁互斥时,会排队串行执行。