| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> MySQL 索引底层原理 -> 正文阅读 |
|
[大数据]MySQL 索引底层原理 |
索引是帮助MySQL高效获取数据的排好序的数据结构。 索引是一种数据结构,数据结构有:二叉树(二叉查找树Binary Search Tree)、红黑树(Red Black Tree)、Hash表、B-Tree、B+Tree 索引详解: 1.假设索引采用二叉树数数据结构: 如图所示:我们建了一张表,一些个人数据,此时以age字段建一个索引,如果采用二叉树数据结构作为索引那么图如下: 此时如果进行查询:select * from user where age=29 ; age为索引字段,会先去存储我们索引的数据页进行查询,29大于24,又小于31,很快找到29这个索引值,并且根据这个key值存储的磁盘文件地址值,再进行一次磁盘IO去查找这个地址存放的目标数据。如果age不是索引字段,则需要数据库一行一行数据去比对,比对6次以后才拿到目标数据,不停的进行磁盘IO,效率很低。 弊端:如果索引字段一直都是一种规律增加,树的高度会很高,而且查询效率依然很低,这种情况下,几乎变成了线性查找。如图: 2.红黑树? 此时红黑树就应运而生,可解决此问题,红黑树不仅具有二叉树的特性,还有自己的附加属性; 1.结点是红色或黑色。 2.根结点是黑色。 3.每个叶子结点都是黑色的空结点(NIL结点)。 4 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点) 5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。 ?这里不做深入讲解(因为我也不是专家);这里解决问题的方式,就是利用红黑树的自旋的特性,如果出现线性的情况,红黑树的节点会进行左旋转或者又旋转,来达到树状结构的自我平衡 简单理解如图: ?旋转重新组成合理的树状结构,这样树的高度降低,查找的效率提高!例如主键: ? ? 在大数据量的情况下,红黑树依然会有性能问题,例如百万或者更多级别的数据,红黑树的高度依然会特别高,因为基本的特性就是二分查找。此时B-Tree就出现了,在纵向高度无法突破的情况下,只能考虑横向扩展,可考虑横向放的索引数据增加,让一个节点存放更多的索引元素,同时可以分更多的叉出来。 ? ? 对红黑树进行一定的改造之后,就可以支撑大数据量的查找,高度可控制在5以内。 ? ?B-Tree : 叶节点具有相同的深度 ,叶节点的指针为空,节点中的数据索引从左到右递增排列。 MySQL的索引底层用的?B+Tree ,是对B-Tree的一个改造,实际上是一个多叉平衡树。 B+Tree :?非叶子节点不存储data,只存储索引,可以放更多的索引;同时叶子节点维护了顺序访问指针(双向指针),提高区间访问的性能。(所有的索引元素都是存储在叶子节点里面,如下图示) ? ? ? ? 相关的索引数据只存储在叶子节点里面,这样做可以让非叶子节点能存储更多的索引,但也并不是说每一个节点索引可以无限存储,因为最后都是会放到内存里面去进行运算查找,需要考虑内存及成本。目前MySQL的每个节点分配的空间可以通过命令查看:
?每个节点分配了16384个字节,也就是16KB的空间。 ? ?那么存储索引的时候,一个节点最多能存储 16k/14B=1170个索引;叶子节点由于存储了索引及相关的数据,叶子节点 假设每组大小为1KB则一个叶子节点可存16个数据;如图所示 ,B+Tree高度为3的时候,理论上所能存储的数据量则为:1170*1170*16=21902400 两千万的数据量。也就是千万级别的数据量情况下,树的高度只有3,效率很高。 ? ? ? ?Hash表:MySQL目前支持BTREE 和 HASH 两种索引方法,也就是两种索引存储数据结构,用Hash散列算法,key为索引值,value为存储数据的磁盘指针数据,同hash算出来的值进行映射,这样进行单条数据查找的时候会非常快,但是一般数据库用的很少,虽然在进行单一数据查找很快,但是hash无法支撑范围查找,范围查找的时候性能会非常低,所支持的场景单一。 ? ? ? ?B+Tree?叶子节点维护有指针,右边元素的索引值都是大于左边的,所以当出现范围查找的时候,只需要找到对应的索引即可找到想要的结果集。顺着指针依次将后面所有的元素放到结果集里面,如果没有这个指针,则会每次都要再从根节点开始去找对应的索引找数据。? ? 不同的存储引擎,底层用B+Tree存储的时候,存储文件还有一点点区别 1.MyISAM的索引文件和数据文件是分离的(非聚集) ? ? ?磁盘上文件存储的时候,一张表至少三个文件,*_myisam.frm 表结构文件,*_myisam.MYD 表数据行文件,*_myisam.MYI 存储表数据的索引(B+Tree结构)。如果是这种类型的存储引擎,命中索引的时候先去 MYI文件中定位到这个索引,找到这个文件中存储的对应的磁盘文件指针,此时(叶子节点的data存储的是这个索引所对应的数据所在磁盘的所在行的文件指针),再去MYD文件中找到对应的数据,放到内存中去。 2.InnoDB的索引实现(聚集),支持事务,用的最多 ? ??表数据本身就是按B+Tree组织的一个索引结构文件,?聚集索引-叶子节点包含了完整的数据记录 ? ? ?一张使用InnoDB存储引擎的表,对应的文件有两个*_innodb_lock_frm (表结构文件)、*_innodb_lock_ibd(存储了索引+数据),(叶子节点里面的data 存储的是相应的行数据),比MyISAM少了一次磁盘IO。 ? ? ?为什么InnoDB必须有主键,且推荐使用整型自增主键? ? ? ?1.如果不设置主键依然可以建表存储,但是底层会自动识别一个字段或者单独建立一个字段作为主键。? ? ? 2.非主键索引,data存储的不是具体的行数据,而是主键索引 ? ? 3.用整型是因为查找索引的时候会经过很多的比较运算操作,这种情况下其他类型效率不会很高,比如用UUID的时候,字符串进行比较,需要逐位对比,如果英文跟数字又需要转位ASCII码来比较大小,影响效率。 ? ? 4.如果非自增主键,就会存在后续新增的数据可能在之前的节点的中间,由于data存储的行数据,一个节点16KB大小,如果本来这个叶子节点已经这么大了,现在又要新增一个主键索引和数据,之前的叶子节点就需要做一个数据页分裂操作,才能将新增的数据加进去,影响性能。用自增,则可以保证每次新增的数据都是在后面,不会遇到数据页分裂的情况。 ? ? ?为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间) |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 19:48:15- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |