InnoDB 索引原理
InnoDB索引原理
索引能够提高访问的速率
B+树索引(最为常用和最为有效)、全文索引、哈希索引。
数据库中的B+树索引可以分为聚集索引和辅助索引,但是不管是聚集还是辅助的索引,其内部都是B+树,是高度平衡的,叶子结点存放着所有的数据。聚集索引和辅助索引最大对的不同就是,叶子结点存放的是否是一整行的信息。
B+树
B+树是为磁盘或者其它直接存取辅助设备设计的一种平衡树,在B+树中,所有纪录结点都是按照键值的大小顺序存放在同一层的叶子结点上,由各叶子结点指针进行连接。
举个例子,上面为index page、下面为leaf page,如下图:
插入
插入分为三种情况,但都必须保证插入后叶子结点中的纪录依然排序。
还是根据上面的那副图作为例子,往里面加入28,我们索引到具体的位置,在25-30中间,我们发现当前的情况为叶子结点不为空,父亲结点也不为空,查询表格发现我们可以直接将纪录插入到叶子结点中,所以如下:
接着往里面插入70,我们发现在叶子结点已经满了,但是父亲结点并没有满,所以需要将叶子结点进行分裂,因为70在最右边,所以将中间的数字60向上移动,放到原来父亲结点中75的位置,而75则向后移动一位,得到如下图:
注意:因为图片大小关系,图中的叶子结点中的双链表没有显示,但是实际是应该显示的。
最后插入95,根据图片索引到其插入位置为叶子结点中90的后面,此时我们发现叶子结点和父亲结点都已经满了,于是它们两个都需要进行分裂,首先将叶子结点中的中间位置85向上移动,并且同时分裂成两个叶子结点(左边比85小,右边比85大),此时父亲结点也放不下85,于是将中间位置的60向上移动单独成为一个结点,左子结点中的值比60小,右子结点的值比60大,具体如下图:
旋转
上面的操作为了保持平衡而进行大量的拆分页操作,因为B+树主要用于磁盘,而拆分则意味着磁盘的操作,所以要在尽可能的情况下减少拆分的动作。B+树也提供了旋转的功能:在当前叶子结点满了,但是兄弟结点没有满的情况下,可以将部分结点移动到兄弟结点中,并且调整父亲结点。
比如在前面提到的加入70,其图可以为:
可以看到,采用旋转操作使得B+树减少了一次页的拆分动作,而且还保持了高度为2。
删除
B+树使用填充因子来控制树的删除变化,填充因子最小可设为50%,同样的,B+树的删除操作需要保证删除后叶子结点中的纪录依然排序,删除分为好几种情况,如下:
我们就继续在插入的树的基础上进行删除操作。删除70后,发现叶子结点和其父亲结点的值的个数并没有小于一半,所以不需要进行其它的操作。
接下来删除25,因为同样是删除表格中的第一种操作,所以直接删除即可,但是需要注意的是,其父亲结点仍然存在25,所以需要将最左边的28更新到父亲结点中即可,如图下:
接着删除60,我们发现删除60后,该叶子结点已经小于填充因子,因此这种情况属于表格中的第三种情况,则需要合并兄弟结点,因为剩余的数字小于75,所以要合并左边的兄弟结点,同时把根结点的60删除掉,合并它的两个子结点,如图下:
索引
数据库中的B+树索引可以分为聚集索引和辅助索引,但是不管是聚集索引还是辅助索引,其内部都是B+树的,即高度平衡的,叶子结点存放着所有的数据,它们不得不同点在于,叶子结点存放的是否是一整行信息。
聚集索引
InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放,而聚集索引就是按照每张表的主键构造一颗B+树,同时叶子结点存放的即为整张表的行纪录数据(聚集索引的叶子结点也称为数据页)。聚集索引的这个特性也决定了索引组织表中数据也是索引的一部分,和B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。
聚集索引的另外一个好处是,它对于主键的排序查找和范围查找速度非常快。叶子结点的数据就是用户所要查询的数据。另外一个是范围查询,即如果要查找住主键某一个范围内的数据,通过叶子结点的上层中间结点就可以得到页的范围,之后直接读取数据页即可。
辅助索引
辅助索引,叶子结点并不包含行纪录的的全部数据,叶子结点除了包含键值以外,每个叶子结点中的索引行还包含了一个书签,该书签用来告诉InnoDB存储引擎哪里可以找到索引相对应的行数据,因为InnoDB存储引擎表是索引组织表,因此辅助索引的书签就是相应行数据的聚集索引键。也就是说当通过辅助索引查找数据时,InnoDB会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键。然后再通过主键索引找到一行完整的数据。
建索引的几大规则
- 最左前缀匹配原则,数据库会一直向右匹配直到遇到范围查询就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的;
- =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序;
- 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,所以最好别对这些字段创建索引;
- 索引列不能参与计算,保持列“干净”,因为B+树中存的都是数据表中的字段值,但进行检索的时候,需要把所有元素都应用函数才能比较,显然成本太大;
- 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可;
索引优化
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描;
例子:select id from t where num is null
应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描;
应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描;(可以使用union来代替or)
in 和 not in 也要慎用,因为in会使系统无法使用索引,而只能直接搜索表中的数据,对于连续的数值,能用 between 就不要用 in;
尽量避免在索引过的字符数据中,使用非打头字母搜索,这也使得引擎无法利用索引;
比如:SELECT * FROM T1 WHERE NAME LIKE ‘%L%’
应尽量避免在 where 子句中对字段进行表达式操作或者函数操作,都会导致引擎放弃使用索引而进行全表扫描;
比如:SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’
应用
联合索引
联合索引是指对表上的多个列进行索引,加快搜索的效率。
覆盖索引
从辅助索引中就可以得到查询的纪录,避免了去查询聚集索引中的纪录所造成的消耗。
InnoDB 索引原理的更多相关文章
- 0614MySQL的InnoDB索引原理详解
转自http://www.cnblogs.com/shijingxiang/articles/4743324.html MySQL的InnoDB索引原理详解 http://www.admin10000 ...
- MySQL系列(九)--InnoDB索引原理
InnoDB在MySQL5.6版本后作为默认存储引擎,也是我们大部分场景要使用的,而InnoDB索引通过B+树实现,叫做B-tree索引.我们默认创建的 索引就是B-tree索引,所以理解B-tree ...
- MySQL的InnoDB索引原理详解
摘要 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本篇 ...
- MySQL的InnoDB索引原理详解 (转)
摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点、主程面试常问问题详解
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- MySQL InnoDB 索引原理
本文由 网易云发布. 作者:范鹏程,网易考拉海购 InnoDB是 MySQL最常用的存储引擎,了解InnoDB存储引擎的索引对于日常工作有很大的益处,索引的存在便是为了加速数据库行记录的检索.以下是 ...
- 深入浅出分析MySQL MyISAM与INNODB索引原理、优缺点分析
本文浅显的分析了MySQL索引的原理及针对主程面试的一些问题,对各种资料进行了分析总结,分享给大家,希望祝大家早上走上属于自己的"成金之路". 学习知识最好的方式是带着问题去研究所 ...
- mySql---剖析InnoDB索引原理
摘要: 本篇为参考别人的文章(http://blog.csdn.net/voidccc/article/details/40077329) 1 各种树形结构 本来不打算从二叉搜索树开始,因为网上已经有 ...
- mysql innodb索引原理
聚集索引(clustered index) innodb存储引擎表是索引组织表,表中数据按照主键顺序存放.其聚集索引就是按照每张表的主键顺序构造一颗B+树,其叶子结点中存放的就是整张表的行记录数据,这 ...
随机推荐
- 在C#中初遇Socket - 2
后期项目实战:多人在线聊天室 源码位置:https://git.oschina.net/z13qu/BlogProjects 前言 第一篇主要对Socket有个基本认识,实现初始化,发送.接受消息:本 ...
- 字符串数组与字符串之间的互转(join/split)
1.Java 1-1.字符串数组=>字符串:StringUtils: join(Object[] array, String separator) 例: Java代码 收藏代码 import o ...
- 【LeetCode】89. Gray Code
题目: The gray code is a binary numeral system where two successive values differ in only one bit. Giv ...
- Java 9 揭秘(7. 创建自定义运行时映像)
Tips 做一个终身学习的人. 在第一章节中,主要介绍以下内容: 什么是自定义运行时映像和JIMAGE格式 如何使用jlink工具创建自定义的运行时映像 如何指定命令名称来运行存储在自定义映像中的应用 ...
- Django开发的基于markdown的博客开源
PiperMarkdown Blog for Django1.11,Python 3.6,based on Markdown,网址,希望大家能给个star,谢谢! 什么是PiperMarkdown 这 ...
- java生成首字母拼音简码的总结
百度找到了某论坛高人写的java(具体论坛记不清了),直接用来调用,再次非常感谢,基本上实现了我的需求 package MD5;import java.util.Scanner;public clas ...
- (转载)oracle 在一个存储过程中调用另一个返回游标的存储过程
原文链接:http://www.jb51.net/article/20160.htm 实际项目当中经常需要在一个存储过程中调用另一个存储过程返回的游标,本文列举了两种情况讲述具体的操作方法. 第一种情 ...
- usaco training 4.2.3 Job Processing 题解
Job Processing题解 IOI'96 A factory is running a production line that requires two operations to be pe ...
- 为Dynamics 365写一个简单程序实现解决方案一键迁移
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复258或者20170627可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- 十年过去了,各位 .net 兄弟还好吗
时间是最无情的,一下子就毕业10年了.很久没有发发牢骚了,今天突然想发一下.看过我文章喷过的知道,我一般都是散文,看完不知道我写了什么,形散而神不散嘛. 十年了,不好意思,没像网上说的标准一样,做管理 ...