InnoDB(4.1):InnoDB的逻辑存储结构简介(表、段、区、页、行)

本文详细介绍了InnoDB存储引擎的索引组织表概念,解释了如何自动选择或创建主键,并通过实例展示了主键的选择过程。此外,还深入探讨了InnoDB的逻辑存储结构,包括表空间、段、区和页的层次,并讨论了页的大小和行的存储限制。最后,提到了innodb_file_per_table参数对表空间的影响。
摘要由CSDN通过智能技术生成

表就是关于特定实体的数据集合,是关系型数据库的核心

索引组织表

在InnoDB存储引擎中,表中的数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表

所以在InnoDB存储的引擎表中,都必须有个主键(primary key),如果在创建表时没有显示地定义主键,则InnoDB存储引擎会按照下面的方式选择或者创建主键

  • 首先判断表中是否有非空的唯一索引,即unique key not null,如果有,那么该列就会变为主键(rowid)
  • 如果有多个非空的唯一索引,则会选择建表时第一个定义的非空唯一索引作为主键(rowid)
  • 如果不符合上述条件,InnoDB存储引擎将自动创建一个6字节大小的指针(rowid)

举个栗子

CREATE TABLE z(
	a INT NOT NULL,
	b INT NULL,
	c INT NOT NULL,
	d INT NOT NULL,
	UNIQUE KEY(b),
	UNIQUE KEY(c),
	UNIQUE KEY(d)
)ENGINE=INNODB,CHARSET=utf8;

从建表上看,可以看到b、c、d列都有唯一索引,但b可以为NUll,故不可以充当主键,而第一个非空唯一索引是c列,所以c将会充当主键。

//插入几条数据
INSERT INTO z SELECT 1,2,3,4;
INSERT INTO z SELECT 1,3,4,5;
INSERT INTO z SELECT 1,4,5,6;
INSERT INTO z SELECT 1,5,6,7;

//查询情况,_rowid可以判断主键是哪一列
SELECT a,b,c,d,_rowid FROM z;

结果如下所示

在这里插入图片描述
可以看到**_rowid**跟c列一模一样,所以可以确定c列成为了主键

但是**_rowid**只可以看单个列作为主键的情况,如果使用多个列作为主键是查询不了的

//当遇到下面的建表语句是无法使用rowid查询的
CREATE TABLE z2(
	a INT NOT NULL,
	b INT NOT NULL,
	c INT NOT NULL,
	PRIMARY KEY(a,b)
)ENGINE=INNODB,CHARSET=utf8;

InnoDB逻辑存储结构

从InnoDB存储的逻辑存储结构看,所有数据都被逻辑地存放在一个空间里面,称之为表空间(tablespace)。而表空间又由段(segment)、区(extent)、页(page)组成,页有时也会被成为块。

其实是段里面的是区,区里面的是页,页里面还有行
在这里插入图片描述

表空间

前面的InnoDB存储文件提到过,所有的数据都是存放在表空间里面的,默认会有一个表空间ibdata1,即所有的数据都会在该表空间里面,不过前面也提到过,如果开启了参数innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内,不过单独的表空间里面只存放的数数据、索引和插入缓冲Bitmap页,其他信息,比如插入缓冲的索引页,回滚信息,锁信息,二次写缓冲等还是存放在原来的共享表空间里面。

这同时也说明了一个问题,即使开启了参数innodb_file_per_table,共享表空间也是会不断增加其大小的,会继续膨胀

表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。

数据段其实就是InnoDB索引底层实现结构的B+树的叶子结点(leaf node segment),索引段即为B+树的非索引结点(Non-leaf node segement),回滚段则比较特殊,后面在介绍

在InnoDB存储引擎中,对段的管理都是由引擎自身所完成的,用户没有权限去进行管理,同时也没有必要去管理。

区是由连续页组成的空间,任何情况下,区的大小都为1MB 2 10 K B 2^{10}KB 210KB),为了保证区中页的连续性(因为页是存储真正数据的,为了让页的存放可以连续,不要断开到另一个区),所以InnoDB存储引擎一次从磁盘申请4~5个区在默认情况下,InnoDB存储引擎页的大小为16KB( 2 6 K B 2^6KB 26KB),即一个区中一共有64( 2 8 K B 2^8KB 28KB)个连续的页

InnoDB中可以使用InnoDB_page_size参数去控制每页的大小,可以设置为4K、8K(默认为16K),这样的话,区中存放的页的数量就会相应的变为256和128,但区的大小仍然为1MB,这是雷打不动的

SHOW VARIABLES LIKE "innodb_page_size";

默认如下
在这里插入图片描述
但是,当用户启用了innodb_file_per_table后,创建的表默认大小是96KB,而一个区至少是1MB,所以创建的表应该至少也为1MB才对,为什么会这样?

其实这是因为,在每隔段开始时,会先用32个页大小的碎片页来存放数据,在使用完这些碎片页才会进行区的申请(直接申请4~5个区),这样做的目的在于,对于一些小表,可以在开始时就占用比较少的空间,节省磁盘容量的开销

页是InnoDB磁盘管理的最小单位,默认的页大小为16KB,可以通过innodb_page_size参数进行修改,若修改完成,则所有表中页的大小都会改变,且不可以再次进行修改,除非产生新的库。

常见的页类型有如下:

  1. 数据页(B-tree Node)
  2. undo页(undo log page)
  3. 系统页(system page)
  4. 事务数据页(transaction system page)
  5. 插入缓冲位图页(insert buffer bitmap)
  6. 插入缓冲空闲列表页(insert buffer free list)
  7. 未压缩的二进制大对象页(uncompressed blob page)
  8. 压缩的二进制大对象页(compressed blob page)

InnoDB存储引擎是面向列(row-oriented)的,也就是说数据是按行来进行存放的(数据表中的一行),而每个页的存放的行记录也是有硬性定义的,最多允许存放7992数量的行记录(计算公式为16 * 1024 /2 - 200,16是指页的大小为16KB)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值