mysql原理(六)核心模型-表
一、索引组织表
在InnoDB当中,表都是根据主键的顺序组织存放的,这种存储方式的表称为索引组织表(Index Organized Table)。
在InnoDB表中,每张表都有主键,如果在创建时没有显示的指定主键,则会按照以下方式选择或创建主键:
1)首先,判断表中是否有唯一且非空的索引(Unique NOT NUll),如果有,则将其指定为主键。
2)如果不符合上述,则InnoDB会自动创建一个6字节的指针。
当表中存在多个唯一且非空的索引时,会选择第一个创建的唯一且非空索引作为主键。
_rowid可以用于查看当前表的主键:
_rowid但是对于多个字段的联合主键是无效的。
二、InnoDB逻辑存储结构
逻辑存储结构从上图可以看出,所有的数据都被逻辑的存放在一个空间中,称之为表空间(tablespace)。表空间由段(segment)、区(extent)、页(page)组成。
2.1 表空间
前面的文章记录了在InnoDB存储引擎当中有一个共享表空间idata1,当启用innodb_file_per_table参数后,每个表有自己的独立表空间。
独立表空间中只存放数据、索引和插入缓冲BitMap页,其他数据,如:回滚信息,插入缓冲索引页,系统事务信息,二次写缓冲等还是存放在共享表空间中。
2.2 段
在上面的图中看到表空间是由段组成的。常见的段有数据段,索引段,回滚段等。由于InnoDB是基于索引组织表的,所以其数据段就是B+树的叶子结点(Leaf node segment),索引段是非叶子结点(Non-leaf node segement)。回滚段在后面详细介绍。段是由存储引擎自己控制的,不需要人为进行操作。
2.3 区
区是由连续的页组成的,每个区默认大小是1M。为了保证区种页的连续性,InnoDB存储引擎一次从磁盘申请4~5个区。InnoBD存储引擎页的大小为16K,则每个区中有64个连续的页。
无论是修改也得大小,还是使用压缩页,每个区的大小都是1M。
2.4 页
页是磁盘上管理的最小单位,在InnoDB中,每个页默认最小是16k,可以通过参数innodb_page_size将大小设置为4K,8K,16K等。设置完成后,则不许进行修改,除非通过导入导出产生新的库。
InnoDB中常见的页类型有:
1)数据页(B+树 Node)
2)系统页
3)undo 页
4)事务数据页
5)插入缓冲位图页
6)插入缓冲空闲列表页
7)未压缩的二进制大对象页
8)压缩的二进制大对象页
2.5 行
数据页是按照行进行存放的,并且有硬性的要求,即每个页中的数据行数是16K/2 - 200 行,即7992行。
三、分区表
分区功能并不是在存储引擎层面完成的,因此,InnoDB,MyISam,NDB等都支持分区。
在mysql5.6中,可以使用以下命令查看是否开启表分区功能:
show variables like '%partition%';
在mysql8中可以使用如下的方式:
mysql> select table_schema, table_name, partition_name,partition_method,partition_expression from information_schema.PARTITIONS where table_name = 'bssp_sys_menu';
+--------------+---------------+----------------+------------------+----------------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | PARTITION_METHOD | PARTITION_EXPRESSION |
+--------------+---------------+----------------+------------------+----------------------+
| bssp | bssp_sys_menu | NULL | NULL | NULL |
+--------------+---------------+----------------+------------------+----------------------+
1 row in set (0.01 sec)
mysql中支持的分区类型是水平分区,且其分区是局部索引分区,即一个分区即存放数据也存放索引。
mysql支持的几种分区类型:
1)RANGE分区:行数据属于一个给定的连续列值的范围,责备加入该分区。
2)LIST分区:和RANGE分区类型相比,只是LIST分区面向离散的值。
3)HASH分区:根据用户自定义的返回值来确定分区,返回值不能为负数。
4)KEY分区:根据mysq提供的hash函数进行分区。
不论以何种方式创建分区,当表中存在主键或唯一索引时,唯一索引可以为空,分区列必须是其一个组成部分(比如联合唯一索引,只要包含一个列就行)。
如果不指定主键和唯一索引,则可以用任何列创建分区。
分区的性能
数据库分为OLTP(在线事务处理应用)和OLAP(在线分析应用)。
对于OLAP,可以很好的提升性能。比如有一张上亿的表,用户需要根据某些列不断的查询。如果我们以时间段对表做分区,则只需要查询该分区的表数据。
对于OLTP,分区要相对小心。通常很少有需要获取超过表中10%数据的要求,而对于只需要获取几条甚至单条数据的请求,B+树的两到三次的IO能够很好的完成操作。并不需要分区方式。相反,设计不好,会带来严重的性能问题。