InnoDB 索引实现

总述:

  • 表数据文件本身就是按照B+Tree组织的一个索引结构文件
  • 聚集索引-叶节点包含了完整的数据记录
  • InnoDB表必须建主键,并且推荐使用整型的自增主键
  • 非主键索引结构叶子节点存储的是主键值

少用HASH创建索引的原因:

  • 仅能满足=IN,不支持范围查找
  • 有HASH冲突
    尽管,对索引的key进行一次hash就可能定位到数据,而且很多时候HASH索引比B+树索引更高效

B-树

基本概念

树中所有结点中孩子结点个数(度)的最大值成为树的阶,通常用m表示。如图,F节点为叶子节点,度为0;B节点只有一个孩子节点D,B的度为1;C有两个孩子节点E和F,C的度为2;整棵树度最大为3(D节点),所以,这棵树的阶m=3。

一棵m阶B-树或者是一棵空树,或者是满足以下条件的m叉树:
1)每个结点最多有m个分支(子树);而最少分支数要看是否为根结点,如果是根结点且不是叶子结点,则至少要有两个分支,非根非叶结点至少有ceil(m/2)个分支,这里ceil代表向上取整。
2)如果一个结点有n-1个关键字,那么该结点有n个分支。这n-1个关键字按照递增顺序排列。
3)每个结点的左子树,关键字全部小于该节点的关键字;每个结点的右子树,关键字全部大于该节点的关键字;
4)结点内各关键字互不相等且按从小到大排列。
5)叶子结点处于同一层;可以用空指针表示,是查找失败到达的位置。

5阶树

根据以上5阶B树进行特点描述,其中最底层叶子节点没有展示:

  1. 其中有个节点有5个子树,为最大度,所以判定为5阶树;
  2. 如果根节点没有关键字,那么就是一个空树;但有一个关键字(其值为30),所以其子树必定为2,因为分支数等于关键字个数+1,但又是根节点,分支至少有2个。
  3. 因为是5阶B树,所以非根非叶节点至少有ceil(5/2)=3个分支。
  4. 除根节点之外,节点关键字个数至少为2,因为分支数至少为3,且分支数比关键字个数多1。
  5. 节点中的关键字都是有序的,且同一层中,左边节点中的关键字均小于右边节点内的关键字。
  6. 下层节点内的关键字取值总是落在由上层节点关键字所划分的区间内,如第二层最左边的节点内的关键字划分了三个区间,<15,15到26, >26,其下层中最左边结点内的关键字都小于15,中间结点的关键字在15和26之间,右边结点的关键字大于26。

注:平衡m叉查找树是指每个关键字的左侧子树与右侧子树的高度差的绝对值不超过1的查找树,其结点结构与上面提到的B-树结点结构相同,由此可见,B-树是平衡m叉查找树,但限制更强,要求所有叶结点都在同一层。

为了将大型数据库文件存储在硬盘上,以减少访问硬盘次数为目的,在此提出了一种平衡(B: balance)多路查找树——B-树结构,它能够在单个节点中存储大量键,并且通过保持树的高度相对较小来存储大键值。由其性能分析可知它的检索效率是相当高的,为了提高 B-树性能’还有很多种B-树的变型,力图对B-树进行改进,比如B+树。

B树在SQL查询中的逻辑

在以上5阶B数的27查询过程中:

  1. 根据根节点找到根节点所在磁盘块,读入内存,进行第一次磁盘I/O操作;
  2. 27比根节点30小,得到左子树的指针p1;
  3. 根据指针p1找到左子树根节点的磁盘块,读入内存,进行第二次磁盘I/O操作;
  4. 比较关键字27,大于该节点所有关键字,得到该节点的右子树指针p2;
  5. 根据p2得到27、28所在磁盘块,读入内存,进行第三次磁盘I/O操作;
  6. 在该磁盘块中找到关键字27。

分析上面过程,进行了三次磁盘I/O操作,三次内存查找。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率,并且每次磁盘I/O取到内存的数据都发挥了作用。而3次磁盘I/O操作是影响整个B-Tree查找效率的决定因素。

B+树

相比于B数,B+树有以下特点:

  • 非叶子节点不存储数据,只存储索引,可以存放更多的索引
  • 叶子节点包含所有索引字段,且暗含排序
  • 叶子节点使用指针链接,提高区间访问性能
B+树结构示意图

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在24层。mysql的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要13次磁盘I/O操作。

数据库中的B+Tree索引可以分为聚集索引(clustered index)和辅助索引(secondary index)。聚集索引的B+Tree中的叶子节点存放的是整张表的行记录数据。辅助索引与聚集索引的区别在于辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的聚集索引键,即主键。当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引找到主键,然后再通过主键在聚集索引中找到完整的行记录数据。以上B+树示意图可以认为是一个聚集索引,叶节点data存放的是完整行记录。

此外,由于B+树节点中关键字有自动排序的特性,所以,建表的时候,应该为表创建一个自增的主键,这样,在插入数据的时候,最新的数据由于主键最大,会自动在数的最右侧叶子节点加入;整数,在内存中进行二分查找可以提高效率。

联合索引

联合索引原理示意图

以上是一个以B树为存储结构的联合索引结构示意图,绿色部分为索引('name','age','position'),紫色部分为其余数据。

最左前缀法则

在联合索引中,要遵循最左前缀法则,即查询从索引的最左前列开始且不跳过索引中的列。

EXPLAIN SELECT * FROM tablez WHERE name = 'Bill' AND age = 30;
EXPLAIN SELECT * FROM tablez WHERE age = 30 AND position = 'dev';
EXPLAIN SELECT * FROM tablez WHERE position = 'dev';

第一句有索引,二三句没有使用到索引。第一句的查询过程为:

  1. 先进行name关键字的值比较,找到了左子树;
  2. 在左子树中,因为name值都相等,然后使用age关键字进行比较,得到了第一个元素;

如果age字段也有多个相等的,且查询条件有使用position关键字,然后则需要进一步比较。联合索引中,查询时关键字依次作为限定条件进行查询。

所以,二三句之所以没有使用索引,原因如下:
如果查询条件一开始就开始查询age,那么会在左子树和右子树中同时找到age=30的记录,实际进行了全表查找。

少用HASH索引

HASH值是一个映射关系,进行等值比较有很突出的优势,但是,如果是比较,HASH值并没有一个固定的升序或者降序关系,所以,在区间查询并没有任何优势。然而,在B树中,由于节点中关键字本身的排序特性以及循环双向链的叶节点结果,范围查找有天然优势。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容