mysql技术内幕(四)表

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

4.1 索引组织表

  在InnoDB 存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table) 。在InnoDB 存储引擎表中,每张表都有个主键(Primary Key ) ,如果在创建表时没有显式地定义主键,则InnoDB 存储引擎会按如下方式选择或创建主键:

  • 首先判断表中是否有非空的唯一索引( Unique NOT NULL) ,如果有,则该列即为主键。
  • 如果不符合上述条件, InnoDB 存储引擎自动创建一个6 字节大小的指针。

   当表中有多个非空唯一索引时, InnoDB 存储引擎将选择建表时第一个定义的非空唯一索引为主键。这里需要非常注意的是,主键的选择根据的是定义索引的顺序,而不是建表时列的顺序。

4.2 InnoDB 逻辑存储结构

  从InnoDB 存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace) 。表空间又由段(segment) 、区(extent) 、页(page) 组成。页在一些文档中有时也称为块( block ) , InnoDB 存储引擎的逻辑存储结构大致如图
mysql技术内幕(四)表_第1张图片

4.2.1 表空间

  表空间可以看做是InnoDB 存储引擎逻辑结构的最高层, 所有的数据都存放在表空间中。在默认情况下InnoDB 存储引擎有一个共享表空间ibdata1 ,即所有数据都存放在这个表空间内。如果用户启用了参数innodb_ file per_table, 则每张表内的数据可以单独放到一个表空间内。

  如果启用了innodb_file_per_table的参数,需要注意的是每张表的表空间内存放的只是数据、索引和插人缓冲Bitmap 页,其他类的数据, 如回滚( undo ) 信息,插入缓冲索引页、系统事务信息, 二次写缓冲( Double write buffer) 等还是存放在原来的共享表空间内。这同时也说明了另一个问题: 即使在启用了参数innodb_file_per_table 之后,共享表空间还是会不断地增加其大小。

4.2.2 段

  表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。
  InnoDB 存储引擎表是索引组织的(index organized) ,因此数据即索引,索引即数据。那么数据段即为B+ 树的叶子节点(图4-1 的Leafnode segment) ,
索引段即为B+ 树的非索引节点(图4-1 的Non-leaf node segment) 。回滚段较为特殊。在InnoDB 存储引擎中,对段的管理都是由引擎自身所完成, DBA 不能也没有必要对其进行控制。这和Oracle 数据库中的自动段空间管理(ASSM) 类似,从一定程度上简化了DBA 对于段的管理。

4.2.3 区

  区是由连续页组成的空间,在任何情况下每个区的大小都为1MB 。为了保证区中页的连续性, InnoDB 存储引擎一次从磁盘申请4~5个区。在默认情况下,InnoDB 存储
引擎页的大小为16KB,即一个区中一共有64个连续的页。lnnoDB 1.0.x 版本开始引入压缩页,即每个页的大小可以通过参数设置为2K 、4K 、8K ,因此每个区对应页的数盘就应该为512 、256 、128

4.2.4 页

  InnoDB 有页(Page) 的概念〈也可以称为块),页是InnoDB磁盘管理的最小单位。在lnnoDB 存储引擎中,默认每个页的大小为16KB。 而从InnoDB 1 .2.x 版本开始, 可以通过参数innodb_page_size 将页的大小设置为4K、8K、16K。若设置完成, 则所有表中页的大小都为innodb_page_size ,不可以对其再次进行修改。除非通过mysqldump 导入和导出操作来产生新的库。
  在InnoDB 存储引擎中,常见的页类型有:

  • 数据页( B-tree Node )
  • undo 页(undo Log Page)
  • 系统页(System Page)
  • 事务数据页( Transaction system Page)
  • 插入缓冲位图页(Insert Buffer Bitmap)
  • 插入缓冲空闲列表页( Insert Buffer Free List)
  • 未压缩的二进制大对象页(Uncompressed BLOB Page)
  • 压缩的二进制大对象页(compressed BLOB page)

4.2.5 行

  InnoDB 存储引擎是面向列的(row-oriented) ,也就说数据是按行进行存放的。每个页存放的行记录也是有硬性定义的,最多允许存放16KB / 2-200 行的记录,即7992 行记录。

4.3 InnoDB 行记录格式

  记录是以行的形式存储的。这意味着页中保存着表中一行行的数据。InnoDB 存储引擎提供了Compact 和Redundant 两种格式来存放行记录数据。

4.3.1 Compact 行记录格式

  Compact 行记录是在MySQL 5.0 中引人的,其设计目标是高效地存储数据。简单来说,一个页中存放的行数据越多,其性能就越高。

4.3.2 Redundant 行记录格式

Redundant是MySQLS .O 版本之前InnoDB 的行记录存储方式. MySQL 5.O 支持Redundant是为了兼容之前版本的页格式。

4.3.3 行溢出数据

  InnoDB 存储引擎可以将一条记录中的某些数据存储在真正的数据页丽之外。一般认为BLOB 、LOB 这类的大对象列类型的存储会把数据存放在数据页面之外。但是,这个
理解有点偏差, BLOB 可以不将数据放在溢出页面,而且即便是VARCHAR 列数据类型,依然有可能被存放为行溢出数据。
首先对VARCHAR 数据类型进行研究 MySQL 数据库的VARCHAR 类型可以存放65 535 字节。但是,这是真的吗?通过实际测试发现能存放VARCHAR类型的最大长度为65532。

到表空间中有一个数据页节点B-tree Node ,另外有4 个未压缩的二进制大对象页Uncompressed BLOB Page,在这些页中才真正存放了65532 字节的数据。实际存放的数据都在BLOB 页中

mysql技术内幕(四)表_第2张图片

4.4 InnoDB 数据页结构

   页是InnoDB 存储引擎管理数据库的最小磁盘单位。页类型为B-tree Node的页存放的即是表中行的实际数据。
   InnoDB 数据页由以下7个部分组成

  • File Header (文件头〉
  • Page Header (页头〉
  • Infimun 和Supremum Records
  • User Records (用户记录,即行记录)
  • Free Space ( 空闲空间〉
  • Page Dircctory (页目录)
  • File Trailer (文件结尾信息〉

   其中File Header、Page Header、File Trailer 的大小是固定的,这些空间用来标记该页的一些信息,如Checksum ,数据页所在B+ 树索引的层数
等。User Records、Free Space、Page Directory 这些部分为实际的行记录存储空间,因此大小是动态的。

图1

4.5 Named File Formats 机制

  略

4.6 约束

4.6.1 数据完整性

   关系型数据库系统和文件系统的一个不同点是, 关系数据库本身能保证存储数据的完整性,不需要应用程序的控制,而文件系统一般需要在程序端进行控制。当前几乎所有的关系型数据库都提供了约束(constraint) 机制,该机制提供了一条强大而简易的途径来保证数据库中数据的完整性。一般来说,数据完整性有以下三种形式:实体完整性保证表中有一个主键。在InnoDB 存储引擎表中,用户可以通过定义Primary Key 或Unique Key 约束来保证实体的完整性。用户还可以通过编写一个触发器来保证数据完整性。

   域完整性保证数据每列的值满足特定的条件。在InnoDB 存储引擎表中,域完整性可以通过以下几种途径来保证:

  • 选择合适的数据类型确保一个数据值满足特定条件。
  • 外键( Foreign Key) 约束。
  • 编写触发器。
  • 还可以考虑用DEFAULT 约束作为强制域完整性的一个方面。

参照完整性保证两张表之间的关系。InnoDB 存储引擎支持外键,因此允许用户定义外键以强制j参照完整性,也可以通过编写触发器以强制执行。
对于InnoDB 存储引擎本身而言, 提供了以下几种约束:

  • Primary Key
  • Unique Key
  • Foreign Key
  • Default
  • NOT NULL
    mysql技术内幕(四)表_第3张图片

4.6.2 约束的创建和查找

4.6.3 约束和索引的区别

Primary Key 和Unique Key 的约束有什么区别呢?
  的确,当用户创建了一个唯一索引就创建了一个唯一的约束。但是约束和索引的概念还是有所不同的, 约束更是一个逻辑的概念, 用来保证数据的完整性,而索引是一个数据结构,既有逻辑上的概念, 在数据库中还代表着物理存储的方式。

4.6.4 对错误数据的约束

  在某些默认设置下, MySQL 数据库允许非法的或不正确的数据的插入或更新,只或者可以在数据库内部将其转化为一个合法的值,如向NOT NULL 的字段插入一个NULL值, MySQL 数据库会将其更改为0 再进行插入, 因此数据库本身没有对数据的正确性进行约束。

4.6.5 ENUM 和SET 约束

  MySQL 数据库不支持传统的CHECK 约束,但是通过ENUM 和SET 类型可以解决部分这样的约束需求。例如表上有一个性别类型,规定域的范围只能是male 或female ,在这种情况下用户可以通过ENUM 类型来进行约束。

4.6.6 触发器与约束

4.6.7 外键约束

外键用来保证参照完整性,MySQL 数据库的MyISAM存储引擎本身并不支持外键,对于外键的定义只是起到一个注释的作用

4.7 视图

4.8 分区表

4.8.1 分区概述

   分区的过程是将一个表或索引分
解为多个更小、更可管理的部分。就访问数据库的应用而言,从逻辑上讲,只有一个表或一个索引,但是在物理上这个表或索引可能由数十个物理分区组成。每个分区都是独立的对象,可以独向处理,也可以作为一个更大对象的一部分进行处理。MySQL 数据库支持的分区类型为水平分区,并不支持垂直分区。此外, MySQL数据库的分区是局部分区索引,一个分区中既存放了数据又存放了索引。而全局分区是
指,数据存放在各个分区中,但是所有数据的索引放在一个对象中。目前, MySQL 数据库还不支持全局分区。

   分区可能会给某些SQL 语句性能带来提高,但是分区主要用于数据库高可用性的管理。在OLTP 应用中,对于分区的使用应该非常小心。总之,如果只是一昧地使用分区,而不理解分区是如何工作的,也不清楚你的应用如何使用分区,那么分区极有可能会对性能产生负面的影响。当前MySQL 数据库支持以下几种类型的分区。

  • RANGE 分区:行数据基于属于一个给定连续区间的列值被放入分区。MySQL 5.5
    开始支持队NGECOLUMNS 的分区。
  • LIST 分区:和RANGE 分区类型,只是LIST 分区面向的是离散的值。MySQL 5.5
    开始支持LIST COLUMNS 的分区。
  • HASH 分区: 根据用户自定义的表达式的返回值来进行分区,返回值不能为负数。
  • KEY 分区:根据MySQL 数据库提供的哈希函数来进行分区。

  不论创建何种类型的分区,如果表中存在主键或唯一索引时,分区列必须是唯一索引的一个组成部分,因此下面创建分区SQL 语句会产生错误。

   分区启用后会根据分区列数据存在不同的物理文件中

你可能感兴趣的:(mysql)