mysql 二叉树表设计_mysql---B+tree索引的设计原理

1.什么是数据库的索引

每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

在向数据库中插入新的数据时,同时也需要向数据库索引中插入相应的索引键值 ,则需要向 B+树 中插入新的键值。

当从数据库中删除数据时,同时也需要从数据库索引中删除相应的索引键值 ,则需要从 B+树 中删 除该键值

在mysql中使用的这种数据结构就是B+tree,它是B-tree的变种。

那么什么是B-tree?

2.B-tree

3.B-tree查找

模拟查找关键字29的过程:

根据根节点找到磁盘块1,读入内存。【磁盘I/O操作第1次】

比较关键字29在区间(17,35),找到磁盘块1的指针P2。

根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第2次】

比较关键字29在区间(26,30),找到磁盘块3的指针P2。

根据P2指针找到磁盘块8,读入内存。【磁盘I/O操作第3次】

在磁盘块8中的关键字列表中找到关键字29。

分析上面过程,发现需要3次磁盘I/O操作,和3次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而3次磁盘I/O操作是影响整个B-Tree查找效率的决定因素。B-Tree相对于AVLTree缩减了节点个数,使每次磁盘I/O取到内存的数据都发挥了作用,从而提高了查询效率。

4.B-tree的插入和删除

假设需依次插入关键字30,26

首先通过查找确定插入的位置。由根a 起进行查找,确定30应插入的在d 节点中。由于*d 中关键字数目不超过2(即m-1),故第一个关键字插入完成:如(b)

同样,通过查找确定关键字26亦应插入 d. 由于d节点关键字数目超过2,此时需要将 *d分裂成两个节点,关键字26及其前、后两个指针仍保留在 *d 节点中,而关键字37 及其前、后两个指针存储到新的产生的节点 *d中。同时将关键字30 和指示节点 *d的指针插入到其双亲的节点中。由于 *b节点中的关键字数目没有超过2,则插入完成.如(c)(d)

5.B+tree

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构, 即B+树是应文件系统所需而产生的一种B-树的变形树。InnoDB存储引擎就是用B+Tree实现其索引结构。

从上一节中的B-Tree结构图中可以看到每个节点中不仅包含数据的key值,还有data值。而每一个页的存储空间是有限的,如果data数据较大时将会导致每个节点(即一个页)能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

B+Tree相对于B-Tree有几点不同:

非叶子节点只存储键值信息。

所有叶子节点之间都有一个链指针。

数据记录都存放在叶子节点中。

6.为什么使用B-Tree(B+Tree)

一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。下面先介绍内存和磁盘存取原理,然后再结合这些原理分析B-/+Tree作为索引的效率。

局部性原理与磁盘预读

由于存储介质的特性,磁盘本身存取就比主存慢很多,再加上机械运动耗费,磁盘的存取速度往往是主存的几百分分之一,因此为了提高效率,要尽量减少磁盘I/O。为了达到这个目的,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。这样做的理论依据是计算机科学中著名的局部性原理:

当一个数据被用到时,其附近的数据也通常会马上被使用。

程序运行期间所需要的数据通常比较集中。

由于磁盘顺序读取的效率很高(不需要寻道时间,只需很少的旋转时间),因此对于具有局部性的程序来说,预读可以提高I/O效率。

预读的长度一般为页(page)的整倍数。页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为4k),主存和磁盘以页为单位交换数据。当程序要读取的数据不在主存中时,会触发一个缺页异常,此时系统会向磁盘发出读盘信号,磁盘会找到数据的起始位置并向后连续读取一页或几页载入内存中,然后异常返回,程序继续运行。

B-/+Tree索引的性能分析

从使用磁盘I/O次数评价索引结构的优劣性:根据B-Tree的定义,可知检索一次最多需要访问h个结点。数据库系统的设计者巧妙的利用了磁盘预读原理,将一个结点的大小设为等于一个页面,这样每个结点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:

每次新建结点时,直接申请一个页面的空间,这样可以保证一个结点的大小等于一个页面,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

B-Tree中一次检索最多需要h-1次I/O(根结点常驻内存),渐进复杂度为O(h)=O(logdN)。一般实际应用中,出读d是非常大的数字,通常超过100,因此h非常小。

综上所述,用B-Tree作为索引结构效率是非常高的。

而红黑树结构,h明显要深得多。由于逻辑上很近的结点(父子结点)物理上可能离得很远,无法利用局部性原理。所以即使红黑树的I/O渐进复杂度也为O(h),但是查找效率明显比B-Tree差得多。

B+Tree更适合外存索引,是和内结点出度d有关。从上面分析可以看到,d越大索引的性能越好,而出度的上限取决于结点内key和data的大小:dmax=floor(pagesize/(keysize+datasize+pointsize))。

floor表示向下取整。由于B+Tree内结点去掉了data域,因此可以拥有更大的出度,拥有更好的性能。

7.MyISAM索引实现

1.主键索引

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。

2.辅助索引

在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:

8.InnoDB索引实现

1.InnoDB主键索引

InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

2.InnoDB辅助索引

InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:

InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB存储引擎中默认每个页的大小为16KB,可通过参数innodb_page_size将页的大小设置为4K、8K、16K,在MySQL中可通过如下命令查看页的大小:show variables like 'innodb_page_size';

系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。

而系统一个磁盘块的存储空间往往没有这么大,因此InnoDB每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小16KB。InnoDB在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时如果一个页中的每条数据都能有助于定位数据记录的位置,这将会减少磁盘I/O次数,提高查询效率。

.推算

InnoDB存储引擎中页的大小为16KB,一般表的主键类型为INT(占用4个字节)或BIGINT(占用8个字节),指针类型也一般为4或8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值(因为是估值,为方便计算,这里的K取值为〖10〗3)。也就是说一个深度为3的B+Tree索引可以维护103 * 10^3 * 10^3 = 10亿 条记录。

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

9.数据库中的B+Tree索引可以分为聚集索引(clustered index)和辅助索引(secondary index)

聚集索引的B+Tree中的叶子节点存放的是整张表的行记录数据。辅助索引与聚集索引的区别在于辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的聚集索引键,即主键。当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引找到主键,然后再通过主键在聚集索引中找到完整的行记录数据。

InnoDB索引和MyISAM索引的区别:

一是主索引的区别,InnoDB的数据文件本身就是索引文件。而MyISAM的索引和数据是分开的。

二是辅助索引的区别:InnoDB的辅助索引data域存储相应记录主键的值而不是地址。而MyISAM的辅助索引和主索引没有多大区别。

所以:

1.不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大

2.用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS_单个或多个文件上传_不支持单独修改

A-From表单直接填写提交地址&#xff0c;不过干预&#xff1a; 1. 单文件上传 最简单的文件上传&#xff0c;是单文件上传&#xff0c;form标签中加入enctype"multipart/form-data"&#xff0c;form表单中有一个input[type"file"]项 <form name"…

一些算法学习的推荐博文阅读(数论居多,图论没有)

上面是自己的学习笔记&#xff0c;下面是推荐博文阅读 关于每个知识点的阅读顺序若不加序号一般是并列的&#xff0c;有序号的话一般是推荐看&#xff08;当然一知半解的话可以从头看起也可以从中间开始&#xff09; 另外&#xff0c;有的链接放在推荐的下面了 另另外&#xff…

scipy是python下的什么_SciPy是什么

SciPy是一个开源的Python算法库和数学工具包。 SciPy包含的模块有最优化、线性代数、积分、插值、特殊函数、快速傅里叶变换、信号处理和图像处理、常微分方程求解和其他科学与工程中常用的计算。SciPy 是一个开源的 Python 算法库和数学工具包。 SciPy 包含的模块有最优化、线…

解码Java.Lang.OutOfMemoryError:PermGen空间

Java开发人员最不了解的领域之一是垃圾收集。 Java开发人员认为JVM负责垃圾收集&#xff0c;因此他们不必担心内存分配&#xff0c;释放等问题。但是&#xff0c;随着应用程序变得越来越复杂&#xff0c;垃圾收集也会变得越来越复杂&#xff0c;一旦性能变得复杂&#xff0c;性…

Python_报错:IndexError: list assignment index out of range

今天发现一个报错&#xff0c;卡了好几个点&#xff0c;后来发现原因后&#xff0c;脸上三条黑线&#xff0c;尴尬啊&#xff01;&#xff01;&#xff01; 报错&#xff1a;IndexError: list assignment index out of range 原因&#xff1a;split()写法转成列表就会认作一个整…

mysql跨服务器查询插入_Oracle跨服务器查询插入数据

想实现insert into 当前库表 select 远程库中的表数据这种方式的数据同步&#xff0c;于是配置了一下oracle服务&#xff0c;远程和本地服务都是oracle 一、在当前库中插入数据 1 2 create public database link remotedb connect to username identified by password using db…

angular-JS模仿Form表单提交

直接上示例代码&#xff0c;有不懂的欢迎留言&#xff1a; $http({url: "http://localhost:10086/yuanxin/Conference/ImportExcelDataForBusRoute",method: Post,headers: {Content-Type: multipart/form-data },data: { BusRoute: file, ConferenceID: "1&…

想要更快地使用AtomicLong? 等待它。

我经常听到Java原子类型&#xff08;java.util.concurrent.atomic&#xff09;超级快&#xff0c;可以很好地与高度并发的代码一起使用。 在大多数情况下&#xff0c;原子以健壮和高效的方式发挥作用。 但是&#xff0c;在某些情况下&#xff0c;原子类型上非托管争用的隐藏成本…

994. 腐烂的橘子

994. 腐烂的橘子 在给定的网格中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。每分钟&#xff0c;任何与腐烂的橘子&#xff08;在 4 个正方向上&#xff09;相邻的新鲜橘子都会腐…

python爬虫简历范文_爬虫数据解析,简历模板下载!想收我Q,不存在的!

目标网址代码基础代码&#xff1a;第一页模板下载import requestsfrom lxml import etreeif __name__ __main__:headers {User-Agent: Mozilla / 5.0(Windows NT 6.1; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 86.0.4240.198 Safari / 537.36}# 免费下…

java获取页面标签_java获取网页源代码后,提取标签内容……

java获取网页源代码后&#xff0c;提取标签内容……关注:245 答案:2 mip版解决时间 2021-02-01 09:11提问者咏b琂败2021-01-31 13:49import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.ne…

C#数字,日期格式化:String.Format

C#:String.Format数字格式化输出 int a 12345678; //格式为sring输出// Label1.Text string.Format("asdfadsf{0}adsfasdf",a);// Label2.Text "asdfadsf"a.ToString()"adsfasdf";// Label1.Text string.Format("asdfadsf{0:C}adsfasdf…

jquery中点击切换的实现

项目中经常会遇到一种情况&#xff0c;就是点击切换&#xff0c;比如点击按钮&#xff0c;div样式为1&#xff0c;再点击一下按钮&#xff0c;div样式为2&#xff0c;再点击一下按钮&#xff0c;div样式为1。需要自定义jQuery方法toggle。 // toggle方法$.fn.toggle function(…

Spring Data MongoDB级联保存在DBRef对象上

默认情况下&#xff0c; Spring Data MongoDB不支持对带有DBRef注释的引用对象的级联操作&#xff0c;如引用所述 &#xff1a; 映射框架不处理级联保存 。 如果更改了Person对象引用的Account对象&#xff0c;则必须单独 保存 Account对象。 在Person对象上调用save 不会自动…

BZOJ4061/Gym100624F CERC2012 Farm and Factory 最短路、切比雪夫距离

传送门——BZOJCH 传送门——Vjudge 设\(f_i\)表示\(i\)到\(1\)号点的最短距离&#xff0c;\(g_i\)表示\(i\)到\(2\)号点的最短距离&#xff0c;\(s_i\)表示\(n1\)号点到\(i\)号点的最短距离&#xff0c;\(As_1,Bs_2\) 根据最短路三角形不等式&#xff0c;\(|f_i - A| \leq s_i…

scrapy安装_爬虫框架Scrapy简介与安装

Scrapy 框架Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架&#xff0c;用途非常广泛。框架的力量&#xff0c;用户只需要定制开发几个模块就可以轻松的实现一个爬虫&#xff0c;用来抓取网页内容以及各种图片&#xff0c;非常之方便。Scrapy 使…

前端面试题(附上自己的回答)

一些开放性题目 1.自我介绍&#xff1a;除了基本个人信息以外&#xff0c;面试官更想听的是你与众不同的地方和你的优势。 2.项目介绍&#xff1f; 3.如何看待前端开发&#xff1f; 4.平时是如何学习前端开发的&#xff1f; 5.未来三到五年的规划是怎样的&#xff1f; position…

汇编语言的基础知识

汇编语言是在硬件上工作的编程语言&#xff0c;我们需要了解硬件系统的结构&#xff0c;才能有效的用汇编语言对其进行编程。 一&#xff1a;汇编语言的组成 1&#xff09;汇编指令&#xff1a;机器码的助记符&#xff0c;有对应的机器码。 2&#xff09;伪指令&#xff1a;没有…

亚马逊Simple Worklfow服务的骆驼演示

在上一篇文章中&#xff0c;我解释了为什么AWS SWF服务很好&#xff0c;并宣布了新的Camel SWF组件。 现在&#xff0c;组件文档已准备就绪&#xff0c; 这是一个简单的完全可用的演示。 它包含三个独立的独立骆驼路线&#xff1a; 工作流生产者允许我们与工作流进行交互。 它…

CODEVS 1205 单词反转

嗯.... 这道题看起来挺像一个字符串的题&#xff0c;但其实却错了&#xff0c;它实质上却用了一个栈进行了一个模拟&#xff08;当然还有一种鬼畜的做法&#xff0c;下面也会介绍到..... 首先先看题&#xff1a; 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题…