共计 2733 个字符,预计需要花费 7 分钟才能阅读完成。
以下是联合网上及此前面试时遇到的一些对于 mysql 索引的面试题。
若对 mysql 索引不太理解可先翻阅相干文章
- 大白话 mysql 之深入浅出索引原理 – 上
大白话 mysql 之深入浅出索引原理 – 下
什么是索引?
索引相似书本的目录,查问书中的指定内容时,先在目录上查找,之后可疾速定位到内容地位。在数据库中通常通过 B 树 /B+ 树数据结构实现。
主键索引和非主键索引有什么区别?
主键索引树中叶子节点存储的是整行数据,而非主键索引叶子节点上保留的是主键的值。应用非主键索引时,先从非主键索引获取到行对应主键 ID,之后再依据 id 在主键索引树上搜寻对应行数据,这个过程也被称为回表。
个别应用什么字段作为主键,为什么?
个别应用 innodb 的自增整数类型作为主键:
- 因为自增,容易保障主键索引的有序性,同时还能防止新数据两头地位插入时导致的页决裂;
- 二级索引叶子节点上保留的是主键值,整数类型主键长度较小,二级索引树占用的空间较小。
索引应用场景
where
为查问条件字段创立索引,以达到疾速过滤指定条件数据的目标。
## order by
当应用 order by 将查问后果按某个字段排序时,可思考为该字段创立索引。没有索引时,会先将查问后果放到内存中进行排序(若内存空间有余,会利用磁盘辅助排序),比拟影响查问效率。
索引自身是有序的,能够间接按索引的程序逐条回表取出数据即可。如果是分页查问,成果更好,这时候只须要取出某个范畴的索引对应的数据,而不须要取出所有满足条件的数据排序后再截取返回分页数据。
join
应用 join 时,为被驱动表的关联字段创立索引,能够无效进步查问效率。比方 select * from t1 straight_join t2 on (t1.a=t2.a) where t1.b = 'xxxx';
t2 的字段 a 上有索引,查问过程会是先从表 1 中顺次取出满足条件的行数据,之后用行数据中的 a 字段去 t2 上匹配后将两表字段拼接返回,此时能应用到 t2.a 的索引,防止了 t2 全表扫描。
索引笼罩
如果 select 字段 +where 字段字段列数不太多且查问频繁时,能够思考为 select 和 where 字段创立联结索引,防止查问时回表,进步查问效率。比方 select a from t where b =‘xx’
, 创立联结索引 (b, a),此时扫描索引树后,就曾经失去须要查问的字段 a 了,不须要再回表。须要留神的是联结索引字段的程序,这个语句无奈应用到索引 (a, b)。
创立索引须要留神的中央
- 最左前缀匹配准则,联结索引须要留神索引字段的程序,mysql 会始终向右匹配直到遇到范畴查问 (>、<、between、like) 就进行匹配,比方
a = 1 and b = 2 and c > 3 and d = 4
, 如果建设 (a,b,c,d) 程序的索引,d 是用不到索引的。
字段是否用到索引的意思是字段是否能利用字段在索引中的有序性进行疾速过滤。索引 (a,b,c,d), 在索引树上是先按 a 进行排序,再按 b 进行排序,以此类推,排序规定相似order by a,b,c,d
。下面查问条件中,a 定值,b 是有序的;b 定值,c 是有序的;c 范畴查问,剩下的 d 是无序的。所以 d 无奈应用到该索引。 - 基数小,区分度低的不适宜创立索引。比方性别,最多基数最多总共就 3 个,此时索引过滤性能不高,查完索引后还需回表,可能比间接全表扫描效率更低。
- 更新频繁的字段创立索引时要衡量索引保护老本。
- 尽量扩大索引,比方曾经有 a 索引,当初要加 (a,b) 的索引,那么只须要批改原来的索引即可。
- 防止对 text 大字段创立索引,会导致索引树太大,查问效率不高。如果大字段前 n 个字符区分度较高,能够思考创立前缀索引,只索引开始的局部字符,这样能够节约索引空间,进步索引效率。其毛病是不能用于 ORDER BY 和 GROUP BY 操作,也不能用于笼罩索引 (因为前缀索引树上只有字段的局部内容,须要进行回表)。
什么时候索引会生效?
- 含糊查问时查问条件以”%”结尾无奈应用到索引
- 应用 or 查问时,只有当所有的查问条件字段都有索引能力应用到,比方
a=1 or b = 2
, 只有当 a 和 b 都有索引能力应用到索引。 - 数据类型呈现隐式转换,如 varchar 不加单引号的时候可能会主动转换为 int 类型,这个时候索引生效。
- 在索引列上应用 IS NULL 或者 IS NOT NULL 时候,索引生效,因为索引不会索引空值。
- 在索引字段上应用”NOT、<>、!=、NOT IN“时是不会应用索引的,这时只会进行全表扫描。
- 对索引字段进行计算操作,函数操作时不会应用索引。
- 当优化器感觉全表扫描速度比索引速度快的时候不会应用索引。个别呈现在全表数据比拟少的状况下,这时全表扫描比在非主键索引上查找后再回表速度可能更快。
- 联结索引时,查找不满足最左匹配规定,无奈应用到联结索引。
innodb 应用 b + 树作为索引模型的起因
Mysql 设计的应用场景比拟宽泛,须要对遍历查问、单条查问、数据更新都须要较好的性能反对。B+ 树的个性是只在叶子节点上存储数据。能够从数据读写方面与哈希表、有序数组、b 树其余几种索引模型进行比拟:
- 哈希表:哈希表只能进行等值查问,在解决范畴查问和排序查问时,须要全表扫描哈希表。
- 有序数组:有序数组在进行数据更新时老本较大。往数组两头地位增加数据时,须要挪动前面的数据地位。
- B 树:b 树在非叶子节点上也存储数据,在遍历数据时,须要对不同层级的节点上的数据进行拼接和排序,这会导致屡次磁盘 io。查问效率较低。
如何删除百万级别或以上的数据?
能够思考先删掉表的索引,等删除数据后再重建索引。当咱们在进行数据批改时,须要同时批改索引,这些额定的索引保护老本较低数据批改的效率;同时,大量的数据删除会导致索引数据页产生大量的碎片空间,此时删除数据后重建索引能够使索引树更“紧凑”,进步磁盘空间利用率。
Innodb 中的 B + 树模型中,N 叉树的 N 是否被批改?
- 通过调整索引字段大小来批改
N 叉树中非叶子节点寄存的是索引信息,索引蕴含 Key 和 Point 指针。Point 指针固定为 6 个字节,如果 Key 为 10 个字节,那么单个索引就是 16 个字节。如果 B + 树中页大小为 16 K,那么一个页就能够存储 1024 个索引,此时 N 就等于 1024。咱们通过扭转 Key 的大小,就能够扭转 N 的值。 - 通过批改页大小间接批改,页越大,每页寄存的索引数量就越多,N 就越大。
数据页调整后,如果数据页太小层数会太深,数据页太大,加载到内存的工夫和单个数据页查问工夫会进步,须要达到均衡才行。
如何晓得语句有没有走索引查问?
能够利用 explain 查看 sql 语句的执行打算,通过执行打算来剖析索引应用状况。
写在最初
喜爱本文的敌人,欢送关注公众号「会玩 code」,专一大白话分享实用技术。
公众号福利
回复【mysql】获取收费测试数据库!!
回复【pdf】获取继续更新海量学习材料!!