InnoDB(4,java 中级工程师面试题
索引组织表
**在 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";
评论