【SQL】⼀棵 B+树能存储多少条数据

B+树的存储容量取决于多个因素,包括树的阶(即每个节点的最大子节点数)、键的大小和每个节点的容量。计算一棵B+树能存储多少条数据,通常需要了解以下参数:

  1. 节点大小:一般情况下,节点大小等于数据库页大小(通常为4KB、8KB或16KB)。
  2. 键的大小:每个键的大小取决于索引列的数据类型。
  3. 指针大小:每个指针(指向子节点或数据记录)占用的空间,通常是固定大小的,比如8字节。

假设:

  • 节点大小:8KB = 8192字节
  • 键的大小:16字节(例如,一个整数键4字节,加上其他元数据)
  • 指针大小:8字节

计算每个节点的阶

假设每个节点最多能存储 n 个键和 n+1 个指针。每个键加上一个指针占用的空间为:
在这里插入图片描述

一个节点最多能存储的键数 n 可以通过以下公式计算:
在这里插入图片描述

对于一个8KB的节点:
在这里插入图片描述

所以,每个节点最多可以存储341个键和342个指针。

计算B+树的存储容量

对于一棵高度为 h 的B+树(根节点高度为0),其最大存储容量 M(h) 可以通过递归公式计算:
在这里插入图片描述

由于 B+树的节点是满的,所以可以近似为:
在这里插入图片描述

假设我们有一棵高度为3的B+树,其存储容量为:
在这里插入图片描述

即,一棵高度为3的B+树大约能存储近4000万条记录。

实际应用中的考虑

  1. 页大小:不同数据库系统的页大小不同,常见的有4KB、8KB、16KB甚至更大。
  2. 键的大小:索引列的数据类型不同,键的大小也会不同。例如,字符串索引的键比整数索引的键大得多。
  3. 内部节点和叶子节点的不同:B+树的内部节点和叶子节点存储的数据不同,内部节点存储键和指针,叶子节点存储键和实际数据记录或指向数据记录的指针。
  4. 数据库实现的细节:不同的数据库系统对B+树的实现细节可能不同,影响其实际的存储容量。

总结

一棵B+树能存储的数据量取决于多种因素,包括节点大小、键的大小和树的高度。一般来说,随着B+树的高度增加,树的存储容量呈指数增长。在实际应用中,需要根据具体的数据库实现和数据特征来计算和优化B+树的存储容量。

Oracle数据库的性能是否比MySQL数据库更高?是否可以借鉴Oracle数据库的设计来优化MySQL数据库的性能,不改输入和查询数据SQL以及MySQL数据库的数据存储,改它的架构和代码能否实现MySQL数据库的性能提升? Oracle有表空间,段,区,数据块,具体数据属于按行结构存储。 阅读官方文档是最系统的《Oracle Database Concepts》《Oracle Database Administrator's Guide》画一下有意思的结构:一、逻辑存储结构+------------------------------+| 块头 (Common & Variable) ||-------------------------------|| 表目录 (Table Directory) ||-------------------------------|| 行目录 (Row Directory) ||-------------------------------|| 空闲空间 (Free Space) ||-------------------------------|| 行数据 (Row Data) |+------------------------------+二、物理存储结构:物理文件结构:+----------------------------------------------+| 文件头 (File Header) - 第一个数据块 ||------------------------------------------------|| 数据块 1 (Data Block 1) ||------------------------------------------------|| 数据块 2 (Data Block 2) ||------------------------------------------------|| ... ||------------------------------------------------|| 数据块 N (Data Block N) |+-----------------------------------------------+数据块内部结构:+------------------------------------------------+| 块头 (Common Header - 20字节) || • 块地址 (DBA) || • 块类型 (Type: 1=data, 2=index, etc) || • SCN (System Change Number) |+-------------------------------------------------+| 变长头 (Variable Header) || • 事务槽 (ITL - Interested Transaction List) || • 表目录 (Table Directory) || • 行目录 (Row Directory) |+-------------------------------------------------+| 行数据区 (Row Data Area) || • 行片段 (Row Pieces) || • 行头 (Row Header) || • 列数据 (Column Data) |+-------------------------------------------------+| 空闲空间 (Free Space) |+-------------------------------------------------+三、核心数据结构行片段结构:+-------------------------------------------+| 行头 (Row Header - 3字节) || • 锁字节 (Lock Byte) || • 列数 (Column Count) || • 簇键ID (Cluster Key ID) || • 标志位 (Flags) |+-------------------------------------------+| 列长度数组 (Column Length Array) || • 列1长度 (1-3字节) || • 列2长度 || • ... |+-------------------------------------------+| 列数据区 (Column Data Area) || • 列1数据 || • 列2数据 || • ... |+-------------------------------------------+五、索引结构 [根节点] | +----------+----------+ | | [分支节点] [分支节点] | | +----+----+ +----+----+ | | | | [叶节点] [叶节点] [叶节点] [叶节点] |数据| |数据| |数据| |数据|叶节点结构:+------------------------------------------------+| 头信息 (Header) ||--------------------------------------------------|| 键值1 + ROWID1 ||--------------------------------------------------|| 键值2 + ROWID2 ||--------------------------------------------------|| ... ||--------------------------------------------------|| 键值N + ROWIDN ||--------------------------------------------------|| 下一叶节点指针 (Next Leaf Block Pointer) |+------------------------------------------------+六、事务管理ITL槽结构:+---------------------------------+| 事务ID (XID) ||-----------------------------------|| 事务槽标志 (Flags) ||-----------------------------------|| 锁信息 (Lock Information) ||-----------------------------------|| SCN (Undo SCN) ||------------------------------------|| 回滚段地址 (Undo Block Address) |+-----------------------------------+ 我们都知道,MySQL 是将数据存储到硬盘、磁盘等外部存储器上的,逻辑存储架构,指的就是 MySQL 是如何组织、存储数据的。逻辑存储结构InnoDB 的所有数据都被逻辑地存放在表空间(tablespace)中,表空间又由段(segment),区/簇(extent),页(page)组成。<img src="https://pic1.zhimg.com/50/v2-9ce6a182fffd612e9743a040586ade38_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="594" data-rawheight="445" data-original-token="v2-956f2996bb3d945e175fbd9f62a761bf" class="origin_image zh-lightbox-thumb" width="594" data-original="https://pica.zhimg.com/v2-9ce6a182fffd612e9743a040586ade38_r.jpg?source=2c26e567"/>表空间(tablespace):表空间可以看做是 InnoDB 存储引擎逻辑结构的最高层 ,所有的数据都是存放在表空间中。默认情况下有一个共享表空间 ibdata1 ,所有数据都放在这个表空间内 。段(segment):表空间由多个段组成,每一个索引在表空间中都有两个段,分别是叶子节点段(数据段)和非叶子节点段(索引段)。叶子节点保存在一个段内,可以更好的保持叶子节点的连续性,可以提升访问磁盘的效率。区(extend):多个页组成一个区,对于不大于16KB 的页来说,一个区是 1MB(64 个连续的 16KB 页或者 128 个 8KB 或者 256 个 4KB),对于大于 16K 的页,都是连续 64 个页组成一个区,比如 128KB 的页对应 2MB 的区,256KB 的页对应 4MB 的区。页(page):固定大小的一段连续空间,默认是 16KB,可以通过参数 nnodb_page_size 设置。是读写操作的最小单位。行(row):指表中的一记录,是存储的基本单位。表空间系统表空间System Tablespace,系统表空间可以对应文件系统上一个或多个实际的文件,默认情况下,InnoDB 会在数据目录下创建一个名为 ibdata1 的文件,大小为 12MB,这个文件就是对应的系统表空间在文件系统上的表示。这个文件是自扩展文件,当不够用的时候它会自己增加文件大小。在一个 MySQL 服务器中,系统表空间只有一份。InnoDB 有四个最基本的系统表:SYS_TABLES:记录了表的名称、每个表对应唯一的 ID、表拥有列的个数、表的类型(包括一些文件格式,行格式等)、MIX_ID、表所属表空间的 ID 等;SYS_COLUMNS:记录了列所属表对应的 ID、列是表中的第几列、列名称、主数据类型、精确数据类型(比如是否允许 NULL 等)、列最多占用存储空间的字节数、列的精度【默认都是0】;SYS_INDEXES:记录了索引所属表对应的 ID、索引的唯一 ID、索引名称、索引包含列的个数、索引类型、索引根页面所在表空间 ID、索引根页面所在的页面号等;SYS_FIELDS:记录了索引列所属索引的 ID、索引列在某个索引中是第几列、索引列的名称等;系统表空间与独立表空间的一个非常明显的不同之处就是在表空间开头有许多记录整个系统属性的页面:<img src="https://picx.zhimg.com/50/v2-e8e5e04f05251786157325e31515155a_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="956" data-original-token="v2-86a95423a9982e248fd3c945dbdf14d5" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://picx.zhimg.com/v2-e8e5e04f05251786157325e31515155a_r.jpg?source=2c26e567"/>独立表空间File-per-table Tablespace,在 MySQL5.6.6 之后,InnoDB 并不会默认地把各个表的数据存储到系统表空间中,而是为每一个表建立一个独立表空间。创建一个表后,会在该表所属数据库对应的子目录下创建一个表示该独立表空间的文件,文件名为 表名.ibd。可以指定使用系统表空间还是独立表空间来存储数据,这个功能由启动参数 innodb_file_per_table 控制,在 my.cnf 配置文件中。独立表空间整体结构如下:<img src="https://picx.zhimg.com/50/v2-3ba83c5006248ddbc2cd4f83439178ea_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="4785" data-rawheight="3186" data-original-token="v2-522ab578aecf20fc2597711c1db896bf" class="origin_image zh-lightbox-thumb" width="4785" data-original="https://picx.zhimg.com/v2-3ba83c5006248ddbc2cd4f83439178ea_r.jpg?source=2c26e567"/>其他表空间撤销表空间(Undo Tablespaces):专门用来存放 undolog 的日志文件。临时表空间(Temporary Tablespaces):存放用户创建的临时表和磁盘内部临时表。通用表空间(General Tablespaces):类似于系统表空间,通用表空间是共享表空间,可以存储多个表的数据。段段不对应表空间中某一个连续的物理区域,而是一个逻辑上的概念,由若干个零散的页面(碎片区)和一系列完整的区组成。一个表空间里面会有很多个段组成。常见的段有数据段、索引段、回滚段等。数据段,leaf node segment:管理叶子节点的数据;索引段,non-leaf node segment:管理非叶子节点的数据;回滚段,rollback segment:存储 undo log,用于实现事务回滚;每向表中插入一记录,本质上就是向该表的聚簇索引以及所有二级索引代表的 B+ 的节点中插入数据。InnoDB 对 B+ 的叶子节点和非叶子节点进行了区别对待,也就是说叶子节点有自己独有的区,非叶子节点也有自己独有的区。存放叶子节点的区的集合就算是一个段,存放非叶子节点的区的集合也算是一个段。也就是说一个索引会生成两个段,一个叶子节点段和一个非叶子节点段。每个索引段的大小是固定的,通常为 16KB。如果索引键的大小超过了 16KB,则需要使用多个索引段来存储。InnoDB 为每个段都定义了一个 INODE Entry 结构来记录段中的属性。<img src="https://picx.zhimg.com/50/v2-042125258ceedc9e82e51d1c7b160e44_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="893" data-original-token="v2-3a77769b26c04e7903c08e2648cdd1f3" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://picx.zhimg.com/v2-042125258ceedc9e82e51d1c7b160e44_r.jpg?source=2c26e567"/>Segment ID:段的唯一 ID;NOT_FULL_N_USED:指在 NOT_FULL 链表中已经使用了多少个页面;三个 List Base Node:分别为段的 FREE 链表、NOT_FULL 链表、FULL 链表定义了头节点;Magic Number:用来标记这个 INODE Entry 是否已经被初始化了(初始化的意思就是把各个字段的值都填进去了)。如果这个数字是值的 97937874,表明该 INODE Entry 已经初始化,否则没有被初始化。Fragment Array Entry:段是一些零散页面和一些完整的区的集合,每个 Fragment Array Entry 结构都对应着一个零散的页面,这个结构占 4 个字节,表示一个零散页面的页号。段链表InnoDB 为每个段中的区对应的 XDES Entry 结构建立了三个链表:FREE 链表:同一个段中,所有页面都是空闲的区对应的 XDES Entry 结构会被加入到这个链表。注意和直属于表空间的FREE链表区别开了,此处的 FREE 链表是附属于某个段的。NOT_FULL 链表:同一个段中,仍有空闲空间的区对应的 XDES Entry 结构会被加入到这个链表。FULL 链表:同一个段中,已经没有空闲空间的区对应的 XDES Entry 结构会被加入到这个链表。每个段都会维护上述的三个链表。区不论是系统表空间还是独立表空间,都可以看成是由若干个区组成的,每 256 个区被划分成一组。对于 16KB 的页来说,连续的 64 个页就是一个区,也就是说一个区默认占用 1MB 空间大小。一个区中的页,在物理空间中是连续的,所以在读取时可以减少随机 IO 的次数,从而提高读取速度。<img src="https://pica.zhimg.com/50/v2-f3dc63ea32a55038b5a59033d828c301_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="954" data-rawheight="822" data-original-token="v2-1bb42ff134dc016026d75db2f6b688fe" class="origin_image zh-lightbox-thumb" width="954" data-original="https://picx.zhimg.com/v2-f3dc63ea32a55038b5a59033d828c301_r.jpg?source=2c26e567"/>第一个组最开始的三个页面的类型是固定的,分别是:FSP_HDR:登记整个表空间的一些整体属性以及本组所有的区。整个表空间只有一个 FSP_HDR 类型的页面。IBUF_BITMAP:存储本组所有的区的所有页面关于 INSERT BUFFER 的信息。INODE:存储了许多称为 INODE 的数据结构。其余各组最开始的两个页面的类型是固定的,分别是:XDES:全称是 extent descriptor,用来登记本组各个区的属性。IBUF_BITMAP:同上。XDES Entry为了方便管理区,MySQL 设计了 XDES Entry(Extent Descriptor Entry)结构,每个区都对应着一个 XDES Entry,这个结构记录了对应的区的一些属性。XDES Entry 结构有 40 字节,大致分为 4 个部分:<img src="https://pic1.zhimg.com/50/v2-84ea0158ab0335bae9e98e0b5fa00640_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="380" data-original-token="v2-7b02f92d1743cdb28f85db9b8349e692" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://picx.zhimg.com/v2-84ea0158ab0335bae9e98e0b5fa00640_r.jpg?source=2c26e567"/>Segment ID:每一个段都有一个唯一的 ID。Segment ID 字段表示该区所在的段,前提是该区已经被分配给某个段了,不然该字段的值没有意义;ListNode:这个部分可以将若干个 XDES Entry 结构串联成一个双向链表;State:区的状态,总共有四种类型。处于 FREE、FREE_FRAG、FULL_FRAG 这三种状态的区都是独立的,算是直属于表空间;而处于 FSEG 状态的区是附属于某个段的:FREE,空闲的区:现在还没有用到这个区中的任何页面;FREE_FRAG,有剩余空间的碎片区:表示碎片区中还有可用的页面;FULL_FRAG,没有剩余空间的碎片区:表示碎片区中的所有页面都被使用,没有空闲页面;FSEG,附属于某个段的区:每一个索引都可以分为叶子节点段和非叶子节点段,除此之外 InnoDB 还会另外定义一些特殊作用的段,在这些段中的数据量很大时将使用区来作为基本的分配单位。Page State Bitmap:这个部分共占用 16 字节,也就是 128 位,一个区默认有 64 个页,这 128 位被划分为 64 个部分,每个部分有 2 位,对应区中的 1 个页。第一个位表示对应的页是否是空闲的,第二个比特位还没有用。区链表把状态为 FREE 的区对应的 XDES Entry 结构通过 List Node 来连接成一个链表,即 FREE 链表;把状态为 FREE_FRAG 的区对应的 XDES Entry 结构通过 List Node 来连接成一个链表,即 FREE_FRAG 链表。把状态为 FULL_FRAG 的区对应的 XDES Entry 结构通过 List Node 来连接成一个链表,即 FULL_FRAG 链表。碎片区段是以区为单位申请存储空间的,一个区默认占用 1MB 的空间,如果为段中很小的数据量申请区,则会造成大量空间的浪费,所以 InnoDB 提出了碎片区的概念,碎片区中的页并不都是为了存储同一个段中的数据而存在的,比如有的页用于段 A,有的用于段 B,有的页甚至哪个段也不属于。碎片区直属于表空间,并不属于任何一个段。为段分配存储空间的策略是:起初向表中插入数据的时候,段是从某个碎片区以单个页面来分配存储空间的;当某个段已经占用了 32 个碎片区页面(半个区)之后,就会申请以完整的区为单位来分配存储空间。数据页记录是按照行来存储的,但是数据库的读取并不是以行为单位的。InnoDB 的数据是按数据页为单位来读写的,即数据库的 I/O 操作的最小单位是页,是磁盘和内存之间交互的基本单位,默认大小为 16KB。<img src="https://picx.zhimg.com/50/v2-f372d7dcaf6254b46e25dfce8e08028c_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="692" data-rawheight="843" data-original-token="v2-865b4ce19b60c401e7b3172a47f37d71" class="origin_image zh-lightbox-thumb" width="692" data-original="https://pica.zhimg.com/v2-f372d7dcaf6254b46e25dfce8e08028c_r.jpg?source=2c26e567"/><img src="https://picx.zhimg.com/50/v2-8249b52f2a647c6a8efb47acc9e4614f_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="962" data-rawheight="602" data-original-token="v2-a346073bfc752e86b6acfabda61ad421" class="origin_image zh-lightbox-thumb" width="962" data-original="https://picx.zhimg.com/v2-8249b52f2a647c6a8efb47acc9e4614f_r.jpg?source=2c26e567"/>在 File Header 中有两个指针,分别指向上一个数据页和下一个数据页,连接起来的页相当于一个双向的链表。数据页中的记录(User Record)按照主键顺序组成单向链表。数据页中有一个页目录,起到记录的索引作用。<img src="https://picx.zhimg.com/50/v2-714f5fc6917d69eb256e52ee759f9760_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1080" data-rawheight="1228" data-original-token="v2-4551e13f506961364884434971c0cc6b" class="origin_image zh-lightbox-thumb" width="1080" data-original="https://picx.zhimg.com/v2-714f5fc6917d69eb256e52ee759f9760_r.jpg?source=2c26e567"/>每个记录组的最后一记录就是组内最大的那记录,并且最后一记录的头信息中会存储该组一共有多少记录,作为 n_owned 字段(上图中粉红色字段)页目录用来存储每组最后一记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量也被称之为槽(slot),每个槽相当于指针指向了不同组的最后一个记录。InnoDB 对每个分组中的记录数都是有规定的,槽内的记录就只有几:第一个分组中的记录只能有 1 记录;最后一个分组中的记录数范围只能在 1-8 之间;剩下的分组中记录数范围只能在 4-8 之间。数据行MySQL 有四种行格式:Redundant,Compact,Dynamic,Compressed。我们可以在创建表的时候指定字符集和行格式。MySQL 5.7 默认使用的是 Dynamic 的行格式。RedundantRedundant 是 MySQL5.0 版本之前的行格式,现在一般不会使用,只有 MySQL 的一些系统表会使用。<img src="https://picx.zhimg.com/50/v2-128c7869b874d73563f578e6603df659_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="682" data-rawheight="243" data-original-token="v2-197a857099b3a5b3ef6ca53795cf076a" class="origin_image zh-lightbox-thumb" width="682" data-original="https://picx.zhimg.com/v2-128c7869b874d73563f578e6603df659_r.jpg?source=2c26e567"/>整个行格式分为记录的额外信息和记录的真实数据两部分,其中记录的额外信息又分为两部分:字段长度偏移列表:会把所有字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成个字段长度偏移列表,字段长度占用的字节数按照列的顺序逆序存放。记录头信息:占用 6 字节,即 48 位,具体如下:名称大小(bit)描述预留位11未使用预留位21未使用delete_mask1该记录是否删除min_rec_mask1B+每层非叶子节点小记录都会添加该标记n_owned4当前记录组拥有记录数heap_no13当前记录在页面堆位置信息n_field10记录中列数量1byte_offs_flag1字段长度偏移列表中每个列对应的偏移量是使用1字节还是2字节表示的next_record16下一记录的相对位置记录的真实数据除了列数据以外,还会为每个记录默认添加一些列(也称为隐藏列),具体如下:DB_ROW_ID(row_id) :占 6 个字节。当表没有定义主键,则选择 unique 键作为主键;如果仍没有,则默认添加一个名为 DB_ROW_ID 的隐藏列作为主键。也就是说这个列只有当没有主键也没有索引时才存在;DB_TRX_ID(transaction_id):占 6 字节。事务 id;DB_ROLL_PTR(roll_pointer):占 7 字节。回滚指针,MVCC 的时候会用到;DB_DELETED_BIT(deleted_bit):占 1 字节,用于标识记录是否已删除;CompactCompact 是一种紧凑的行格式,设计的初衷就是为了让一个数据页中可以存放更多的数据行。Compact 描述信息的格式如下:<img src="https://picx.zhimg.com/50/v2-e5aa977ea2a852f69bad56ba4665af40_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1381" data-rawheight="451" data-original-token="v2-3bfe4aeb2e840854fbfd04c1c5ba58eb" class="origin_image zh-lightbox-thumb" width="1381" data-original="https://pic1.zhimg.com/v2-e5aa977ea2a852f69bad56ba4665af40_r.jpg?source=2c26e567"/>变长字段长度列表中存储的是每个非空的变长字段的数据长度,同样也是逆序存放的。如果表中没有变长的数据类型的话,就不需要该列表了。如果长度小于 255B,就用 1B 表示,否则用 2B 表示,最大不会超过 2B,因为 MySQL 中变长类型的最大字节长度限制为 65535。如果表中没有允许 NULL 的列,那么 NULL 标记位就不存在了。否则将每个允许存储 NULL 的列对应一个二进制位并且逆序存放,然后将允许为 NULL 的位标为 1,不允许的标为 0;且必须用整数个字节的位表示,否则在高位补 0。Compact 格式的记录头具体信息如下:名称大小(bit)描述预留位11未使用预留位21未使用delete_mask1该记录是否删除min_rec_mask1B+每层非叶子节点小记录都会添加该标记n_owned4当前记录组拥有记录数heap_no13当前记录在页面堆位置信息record_type3表⽰当前记录的类型,0表⽰普通记录,1表⽰B+⾮叶⼦节点记录,2表⽰⼩记录,3表⽰⼤记录next_record16下一记录的相对位置相比 Redundant,多了一个 record_type 字段,少了 n_field 和 1byte_offs_flag 两个字段。 Compact 的隐藏列和 Redundant 相同。Compact 格式下,具有 65535 字节的最大行大小限制,但是设置允许 NULL 需要占用 1 个字节,设置为变长(varchar)需要占用两个字节。在不同的编码格式下,一个字符占用的字节是不同的,比如 encode=utf8 时,三个字节表示一个字符。数据页默认大小为 16KB,即 16*1024=16384byte,所以当要存储地单行数据超过 16384byte 时,会发生行溢出。但在 MySQL 的设定中,会提早发生行溢出。当列的类型为 VARCHAR、 VARBINARY、 BLOB、TEXT 时,该列超过 768byte 的数据溢出存放到溢出页中,然后通过一个偏移量指针将两者关联起来,这就是行溢出机制。这样可以有效地防止单个列太大导致单个数据页中存放的行记录过少而让 IO 飙升的情况。<img src="https://pica.zhimg.com/50/v2-4bcec5f0393dc97e2ce80196947e5338_720w.jpg?source=2c26e567" data-caption="" data-size="normal" data-rawwidth="1160" data-rawheight="627" data-original-token="v2-1617a0ada445b6eb15f1d6bbdd39b0c3" class="origin_image zh-lightbox-thumb" width="1160" data-original="https://picx.zhimg.com/v2-4bcec5f0393dc97e2ce80196947e5338_r.jpg?source=2c26e567"/>Compact 能比 Redundant 格式节约 20% 的存储空间。DynamicDynamic 和 Compact 行格式类似,只是在处理行溢出数据时有区别。Dynamic 的数据页不会存储真实数据的前 768 字节,而是存储 20 个字节的指针来指向溢出页,即将所有的溢出数据都存在溢出页中。CompressedCompressed 与 Dynamic 相似,区别是 Compressed 存储的行数据会以 zlib 的算法进行压缩以节省空间,因此对于 BLOB、TEXT、VARCHAR 这类大长度类型的数据能够进行非常有效的存储数据字典系统表中保存了许多额外的信息,包括表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、存储过程、触发器等内容,这些数据统称为元数据(元信息),这些元数据的集合(系统表)就成为数据字典。在 MySQL8.0 以前,数据字典是以文件的形式存储的,在 MySQL8.0 以后,全都存放到数据库系统表中了。最后本文介绍了 MySQL 底层的逻辑存储结构,每一数据都是一个数据行,数据行是存储数据的基本单位。若干数据会组成一个数据页,数据页是读写的基本单位,可以减少磁盘 IO 的次数。若干个连续的页会组成一个区,可以降低随机 IO 的次数,来提高查询效率,同时也便于进行管理。不同的区可以按照逻辑分布到不同的段中,可以更好地进行数据管理以及提高空间利用率。
最新发布
12-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值