MySQL索引自己整理的笔记希望能帮到大家

面试题

MySQL索引

索引为什么不用二叉树

如果索引是自增,就像上图这种情况,树状结构右边的子节点肯定是大于父节点的,那么就跟链表结构没有区别。最终跟全盘扫描没什么区别。还是会从磁盘中一次一次的遍历寻找。

假设我要查找7这个元素那么最多也要查找7次才能找到存储节点的指针信息

变成链表结构效率极低

索引为什么不用红黑树(局部平衡)

在这里插入图片描述

红黑树只能局部平衡,当右边的子节点大于一个节点并且左边没有节点的时候会自动平衡(节点单边增长的元素不能2以上,不然就会平衡)

假设我要查找7这个元素那么最多也要查找4次,比二叉树快多了,但是在大数量中,单一节点上扩张,有点浪费。

数据量越大查找效率越低

结论:从上面得出查询的次数跟树的高度有关,那么如果将高度减少,查询的速度是不是就变快了呢

纵向不能发展,那就横向发展

横向存储的元素越多,树的高度越小

B树

疑问1:为什么不把全部数据都放到一个节点上?

因为假设有几千万的数据都放一个节点上面,从磁盘上读取几个G的内容,内存RAM吃不消,IO慢。

所以节点的大小得合适,mysql对节点得大小设置的是16kb(可以通过show global status like 'Innodb_page_size')查看。

MySQL不是用的b树,而是对b树做了一点点改造得到了一种叫 b+树的数据结构

b+树

空白格子存储的是下一个节点的磁盘地址

一般主键都是bigint类型占8个字节(8b)

mysql源码对这个空白位置地址分配了大小大概是6个字节(6b)

索引|地址|索引|地址…也就是说mysql配置的默认16kb大概可以放1170个索引在这里

假设叶子节点一个元素占1kb那么就能放16个元素,那么树的高度是3且所有元素都装满了,通过

1170*1170*16就能算出所有的索引元素个数。

B+树比B树叶子节点多一个指针,就是为了支撑范围查找。

B+树叶子节点从左到右依次递增的趋势,每两个节点有一个双向指针,这样就能支持范围查询。如果没有这个指针,那么每次都要从根节点重新开始找。

疑问1:为什么要把子节点的data移到叶子节点上

因为1:一个节点放16kb大小,将data数据移到叶子节点就能放更多的索引了。

疑问2:为什么要有冗余索引?

因为2:冗余加快查找速度,减少内存的消耗。

Hash

通过特定的MySQL的Hash算法就能得出数据的地址信息,但是不使用它,因为它只支持等值查询、无法排序、存在hash冲突虽然MySQL底层解决冲突很好。

MySQL存储引擎

存储引擎是形容表的

MyISAM

.frm(表的框架信息)

.MYD(data表的数据行记录)

.MYI(index存储表的索引字段)

如果字段是索引,那么就先去MYI文件查找索引所在磁盘的哪个文件地址,根据文件地址指针就能定位到MYD。

MyISAM查询数据需要回表

InnoDB

.ibd(index,data,数据文件和索引文件的合并)
在这里插入图片描述

聚集索引(聚簇索引)聚合的意思就是 主键和数据是放在一起的。

innoDB必须要有主键索引,如果没有建主键,它会自动在你唯一字段里变成主键,如果没有唯一的字段,它会自动建一个隐藏的rowId。

疑问1:为什么推荐使用整形的自增主键?

因为1:整型做比较的时候比较快(1<2 abc<dbc),字符串还需要转成ASCII码去比对,而且整型占用的存储空间更有优势,节约资源。

联合索引

索引最左侧原理,如果第一个字段不是建立索引的第一个字段那么就会失效,比如:

(a,b,c),就只能 a,b,c|a,b|a索引才会生效

Explain

以下通过explain显示出mysql执行的字段内容:

  • id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
  • select_type: SELECT 查询的类型.
  • table: 查询的是哪个表
  • partitions: 匹配的分区
  • type: join 类型
  • possible_keys: 此次查询中可能选用的索引
  • key: 此次查询中确切使用到的索引.
  • ref: 哪个字段或常数与 key 一起被使用
  • rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
  • filtered: 表示此查询条件所过滤的数据的百分比
  • extra: 额外的信息

索引查询失效的几个情况

1、like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效。

2、or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效

3、组合索引,不是使用第一列索引,索引失效。

4、数据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。

5、在索引列上使用 IS NULL 或 IS NOT NULL操作。索引是不索引空值的,所以这样的操作不能使用索引,可以用其他的办法处理,例如:数字类型,判断大于0,字符串类型设置一个默认值,判断是否等于默认值即可。

6、在索引字段上使用not,<>,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。

7、对索引字段进行计算操作、字段上使用函数。(索引为 emp(ename,empno,sal))

8、当全表扫描速度比索引速度快时,mysql会使用全表扫描,此时索引失效。

经供参考,如有不足错误,请纠正,互相帮助!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值