1. 表是顺序存放的
    mysql中所有的表都有主键,即使自己没有显示定义也会根据非空唯一索引,或者自动创建6字节大小的指针作为主键,当有多个非空唯一索引时按照索引定义顺序选择,这个表存储方式叫索引组织表。
    如果单个列为主键时可以通过查询语句加_rowid来查看哪个列作为了主键,因为他会和作为主键的值一样。
  2. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_数据

  3. innodb逻辑存储结构
    innodb逻辑存储由表空间组成,参数innodb_file_per_table可以用来开启每张表使用一个表空间,默认情况下共用一个表空间ibdata1,如果开启了每张表使用一个表空间,这个表空间中只放数据、索引、插入缓冲页,其它数据还是放共享空间内。
  4. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_mysql_02

  5. 1)表空间一旦增加后就不会减小,但是会在表空间中标记出可用空间,下次申请空间时先使用可用空间,最后才增加文件大小。想要了解表空间信息可用参考表空间信息读取工具 2)前面说过MySQL的表存储是索引组织表,也就是数据即所有,即数据段就是B+树的叶子节点,索引段为B+树的非叶子节点。
    3)区是组成段的最小单位,每个区大小都是1m,但是每个段的开始时,先用32个页大小的碎片页来存放数据,用来应对小表之类的节约磁盘开销。
    4)页是组成区的最小单位,默认大小16k可以 通过innodb_page_size来设置页的大小为4k、8k、16k,可用算出来每个区中页的数量1m/16k,一旦设置该参数,所有的表的页都是这个大小,只能通过导入导出产生新的库来改变,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)。
  6. 行记录格式
    dynamic格式5.7中innode使用的格式,可以使用show table status like ‘client%’ \G命令查看格式
  7. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_表空间_03

  8. 其中变成字段长度按照列的顺序逆序放置的最多两个字节,当列的长度小于255字节时使用一个字节表示,当大于255个字节时使用两个字节,例如03 01 02这个代表第一个可变列的长度为2,第二个可变列长度为1,第三个可变列长度为3,null标志位占用一个字节,使用1表示该行有null值,例如05,转为二进制为00000101,说明第一列和第三列为空,那么列数据中就直接没有该数据
  9. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_表_04

  10. 记录头信息见下表表示,共40位
  11. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_mysql数据库怎么显示ER图_05

  12. 另外需要注意的是除了这些信息外,每行还有两个隐藏列,事务id列占用6字节和回滚指针列占用7字节,如果没有定义主键还会增加一个6字节的rowid列
    当数据为blob时,数据页只存放20个字节的指针,真实的数据会放到二进制大对象页。
    当类型为char时,它会受到字符编码的影响,当使用单字节的编码格式(如latin1)时,数据不足的地方会使用0x20来填充,而当使用多字节的编码格式时(如utf-8)它被视为变长字符类型。
  13. 数据页结构
    数据页由7个部分组成,1)file header 一些头信息38字节、2)page header 页的状态信息56字节、3)行记录、4)空闲、5)页目录存放相对位置、6)file trailer 页的完整性检测8字节
  14. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_mysql_06

  15. 使用表空间信息读取工具查看空间信息,如图00000003页是B-tree Node代表数据页,那么所在位置为3*页大小16k=0xc000
    可以按照规则进行读取该文件,这就不再做介绍。
  16. 约束不常用到的技术
    1).当向非空列插入空时,如果报警告而不是错可以调整sql_mode参数设置
    1】ONLY_FULL_GROUP_BY select的列必须在分组中出现,
    2】STRICT_TRANS_TABLES如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做任何限制
    3】NO_ZERO_IN_DATE不接受月或日部分为0的日期
    4】NO_ZERO_DATE不要将 '0000-00-00’做为合法日期
    5】ERROR_FOR_DIVISION_BY_ZERO在INSERT或UPDATE过程中,如果被零除(或MOD(X,0)),则产生错误(否则为警告)
    6】NO_AUTO_CREATE_USER防止GRANT自动创建新用户,除非还指定了密码
    7】NO_ENGINE_SUBSTITUTION如果需要的存储引擎被禁用或未编译,那么抛出错误
    8】ANSI模式:宽松模式,更改语法和行为,使其更符合标准SQL
    9】TRADITIONAL模式:严格模式,当向mysql数据库插入数据时,进行数据的严格校验,保证错误数据不能插入
    2).当想限定某个字段只能是对应的值时,我们可用使用enum类型来约束,如果范围过于复杂,需要程序约束时只能使用触发器了
  17. 视图
    当我们的取数来源于多个物理表时,通常为了查询速度,可用创建一个视图,取数来自视图表。
    当我们视图来源表的变化很小,或者是很规律时,为了加快查询速度,可通过触发器自己做一个物化视图,就是这个视图表是真实的表了,当来源表有修改时通过触发器来进行相关修改。
  18. 分区
    分区加快访问的原理是减少一个分区的数据量,也就意味着降低B+树的层数,数据查询速度和B+树的层数成线性关系,也就是如果数据量不高,或者访问的限定条件不固定,使用分区只会使访问速度更慢。
    目前mysql支持1)range分区,当行数据属于一个给定的连续区间时可用采用。2)list分区,当行数据属于一个集合时可以使用。3)hash分区,根据用户自定义的表达式返回值进行分区。4)key分区,根据数据库提供的哈希函数进行分区。
    可用使用命令 show variables like ‘%partition%’ \G
  19. mysql数据库怎么显示ER图 mysql怎么显示数据库里的表_数据_07

  20. 分区创建语句如下
create table a
(
    a int,
    b datetime
) engine = innodb
    partition by range (year(b))(
        partition p2019 values less than (2020),
        partition p2018 values less than (2019)
        );
create table b
(
    a int,
    b int
) engine = innodb
    partition by list (b)(
        partition p0 values in (null,1,2,3),
        partition p1 values in (4,5,6,7)
        );
create table c
(
    a int,
    b datetime
) engine = innodb
    partition by hash (year(b))
        partitions 2;
create table c
(
    a int,
    b int
) engine = innodb
    partition by key (b)
        partitions 2;