MySQL索引知识 一文全了解,面试前必备
Posted Z-hhhhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL索引知识 一文全了解,面试前必备相关的知识,希望对你有一定的参考价值。
索引
索引(index)是帮助mysql高效获取数据结构。
索引的本质:索引是数据结构,索引的目的是提高查询效率,可以类比新华字典的拼音部分目录,可以根据目录快速定位到每个字的地址。加入没有目录。就需要把字典从头翻到尾,遍历一遍。
索引的优劣
索引的优势
- 提高数据检索的效率,降低数据库IO成本
- 通过索引对数据进行排序,能够降低排序成本,降低CPU的消耗
- 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间
索引的劣势
- 要创建和维护索引都需要消耗时间和物理空间,这些消耗为随着数据量的增加二增加。
- 对表的数据进行增删改的时候,索引也需要进行维护,这就降低了整体的维护速度。
- 当表比较小的时候,直接进行全表扫描反而效率更高
为什么使用自增列做主键
- 如果定义了主键(PRIMARY KEY),那么InnerDB(5.5.8版本后Mysql的默认数据库引擎)会选择主键作为聚集索引。如果没有显示定义主键,那么InnerDB会选择第一个不包含NULL值得唯一所以作为主键索引,如果也不存在这样得唯一索引,那么InnerDB会简历一个隐性的聚集索引,这个索引会就像一个主键一样,随着行的增加而递增。
- 由于数据记录本身被存于主索引(B+Tree)的叶子节点上,这就要求同一个叶子节点内同的各条数据记录按照主键的顺序存放,每当有新的记录插入时,MySQL会根据其主键插入到适当的位置,如果表使用自增主键,那么每次有新的记录插入时,该记录就会按照顺序添加当前的索引到后续位置上,当这一页写满(InnerDB默认时达到15/16的情况下),就会自动开辟新的一页。
- 如果使用非自增主键(身份证号、学号等),因为这样的主键不能保证完全连续,所以每次插入新的记录时,索引就会插入到中间位置。这就导致为了加入新的索引时,需要移动后面的索引数据,需要从磁盘上进行读写操作,同时频繁的移动和分页会早上大量的磁盘碎片,使索引结构不够紧凑,需要通过OPTIMIZE TBALE(优化表)来重新建表并优化填充页面。
BTree和B+Tree区别
BTree
BTree是对平衡二叉树的改造,通过增加树的叉数,将树从高瘦型转变成矮胖,这样数据深度就降低了,从而降低磁盘IO的次数,这样查询数据的效率就提高了。
B树图如下:
主要特点:
- B树的节点中存储多个元素,每个内节点有多个分叉。
- 节点中的元素包含键值和数据,节点中的键值从大到小排列。
- 父节点当中的元素不会出现在子节点中。
- 所有的叶子节点都在同一层,叶节点具有相同的深度,也结点之间没有指针连接。
BTree的缺点
- B树无法支持范围的快速查询,在查询的过程中需要多次回到根节点重新遍历查找,效率比较低。
- 如果data存储的是行记录,行的大小随着列数的增加,空间占用量会增加,这时,一页中可存储的数据量就会减少,树就会变高,磁盘的IO次数也随之增加。
B+Tree树
B+Tree树时对B树的升级,主要区别在于非叶子节点是否储存数据的问题
!区别!
BTree树在非叶子节点和叶子节点都会存储数据
B+Tree树:只在叶子节点才会储存数据,非叶子节点只存键值。叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序的链表。
叶子结点的左右两侧指针域省略。它的特点就是任何非叶子结点都会在叶结点上再次出现一次,并且所有叶子结点从左到右链接了起来。总体来说,它也具备B树的特性,只是在两个方面有所区别。第一就是查找元素时,即使在非叶子结点找到了目标值,它也只是用来索引的,还需要继续找到它在叶子结点的位置。第二就是如果要遍历,只需要遍历一次叶子结点即可。B+树的结构也十分适合范围查找,只需要找到范围的最小值所在位置,然后沿链表遍历即可。
B树 VS B+树(B+树更加适合数据库索引)
①B+树的磁盘读写代价更低
B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了;
②B+树查询效率更加稳定
由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当;
③B+树便于范围查询(最重要的原因,范围查找是数据库的常态)
B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低;
hash索引和BTree区别
hash索引,其检索效率虽然高,可以一次性定位到目标,不像B树那样从根节点到叶子节点那样 需要多次IO 访问
但是hash索引却具有五个缺点,导致我们在Mysql中不使用它。
①hash索引仅仅能满足= IN <> 这三种查询,无法支持范围查询
由于hash索引时进行hash计算,得到hash值,索引它只能进行等值过滤,经过hash算法处理后的hash值无法比较原来的大小,所以不能进行范围比较,
②hash索引无法被用来数据排序
还是由于计算hash值,和原来的大小无法保持一致,因此无法进行排序
③hash索引不能不能利用部分索引键查询
对于组合索引,hash索引在计算hash值的时候时合并在一起计算的,不能单独计算hash值,所以当使用组合索引时,hash索引就无能为力了
④hash索引在任何时候都无法避免扫描表
Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。
⑤hash碰撞
当遇到大量hash值相同的情况下,将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。
索引失效
1、like以%开头,索引无效,但是若是前缀没有%,后缀有%时,索引依旧有效
2、or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效
3、组合索引,不是使用第一列索引,索引失效。
4、数据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。
5、如果mysql估计使用全表扫描要比使用索引快,则不使用索引
以上是关于MySQL索引知识 一文全了解,面试前必备的主要内容,如果未能解决你的问题,请参考以下文章