1 minute read


索引组织表
按主键


逻辑存储结构
=> 所有数据都被逻辑地放置在表空间内,又分别由以下组成 segment, extent, page, row



1.每张表的独立表空间存放:数据、索引、插入缓冲Bitmap页
   共享表空间内存放:回滚信息、插入缓冲索引页、系统事务信息、二次写缓冲等
   共享表空间还是会不断增大

2.数据段:B+树的叶子节点
   索引段:B+树的非叶子节点

3.区大小 1MB,内部有64个页,每个页是16k
   即使引入压缩页,但区的大小始终是1M,同时页的大小也是可以自定义的
mysql> show variables like 'innodb_page%'\g;
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+

实际情况是:每个段开始时,现有32个碎片页来存放数据,使用完后才会申请64个连续页
可以使用py_innodb_page_info.py工具查看idb文件的页分配;

4.行记录格式  Row_format:Compat


变长字段长度列表:各列的长度,每列用1-2字节表示
NULL标记位:用位来标记各列是否有NULL
记录头信息:5字节长度,记录了是否删除、下一记录指针等
列数据:

5.行溢出数据
    所有VARCHAR列的长度总和不能超过65535字节的数据,否则要求使用text或blob
    但超过时,部分数据放在B-tree Node的子节点上,另外的数据作为溢出数据放在blob页中
    
    ? 放多少数据在B+Node上,多少在Blob页上呢?
    =>原则是,因为按索引组织即B+结构,需确保每个页16k上至少有2条记录,否则索引结构失去意义,即8098字节

    对于TEXT和Blob的数据类型,是放在数据页还是Blob页,需看是否一个页能否存放2条记录
    =>实际数据页只保存数据的前768字节

6.新的行记录格式 
新增2种新的行记录格式:Compressed, Dynamic
5.6默认使用格式 Compact
5.7默认使用格式 Dynamic

=> 新格式对于存放在Blob中的数据采用了完全的行溢出方式,在数据页中只存放20个字节的指针,实际数据都放在Blob页中



Innodb数据页格式
1.数据页格式
1.File Header:头信息,如页类型,表空间中也的偏移,上一个/下一个页的指针
2.Page Header:状态信息,如记录数,插入记录的位置,在索引数中的level层
3.Infimum/Supremum:记录的主键值的上下边界
4.User Record:实际存储数据
5.Free Space:空间空间
6.Page Directory:记录的相对位置,将所有记录的主键按顺序存放,便于二叉查找记录
7.File Trailer:尾信息,用于保证页的完整性

要点:
1.B+树索引用来快速找到记录所在的页,不能找到具体的一条记录;
2.页载入内存后,通过Page Directory的有序主键做二叉查找,找到具体的记录;

2.解决页兼容问题 Named File Formats机制
//5.6中
mysql> show variables like '%file_format'\g;
+--------------------+----------+
| Variable_name      | Value    |
+--------------------+----------+
| innodb_file_format | Antelope |
+--------------------+----------+

//5.7中
mysql root@[localhost:mysql3306.sock carddb_20001] > show variables like '%file_format%'\g;
+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| innodb_file_format       | Barracuda |
| innodb_file_format_check | ON        |
| innodb_file_format_max   | Barracuda |
+--------------------------+-----------+



约束和索引
1.索引是一个数据结构,既有逻辑上的概念,用于B+树代表物理存储方式
   约束是逻辑的概念,用于保证数据的完整性
   
    索引类型有:主键索引,唯一索引,全文索引
    约束类型有:主键约束、唯一约束、外键约束、默认值

2.查找约束,表 information_schema.table_constraints
mysql root@[localhost:mysql3306.sock (none)] > select * from information_schema.table_constraints;
+--------------------+-------------------+------------------+--------------+---------------------------+-----------------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME  | TABLE_SCHEMA | TABLE_NAME                | CONSTRAINT_TYPE |
+--------------------+-------------------+------------------+--------------+---------------------------+-----------------+
| def                | carddb_10000      | PRIMARY          | carddb_10000 | t_account                 | PRIMARY KEY     |
| def                | carddb_11000      | Index_SRedeem_ID | carddb_11000 | t_sredeem                 | UNIQUE          |

3.对输入值做合法性约束检查        STRICT_TRANS_TABLES
mysql root@[localhost:mysql3306.sock (none)] > show variables like '%sql_mode%'\g;
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                                     |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

4.Enum约束,目前只能实现枚举离散约束,不能实现完整的check约束
sex ENUM('male', 'femaile')

5.创建触发器trigger
create trigger 触发器名 BEFORE/AFTER UPDATE/DELETE/INSERT on 表名 for each row
begin
if new.cache > old.cache then
xxxx
endif;
end;
$$

6.创建外键,即时检查
foreign key (列名) references 表名(列名) 
on delete 选项
on update 选项
可供选择的选项有:
set null             字表数据设置为null
no action          抛出错误,不允许
restrict              抛出错误,不允许(默认)
cascade            更新,也执行update/delete操作
show variables like 'foreign_key_checks'\g;
|foreign_key_checks | ON    |

6.实现完整性约束的手段:
主键/唯一键:
Enum约束:离散数值
创建触发器:保证操作完整性
外键约束:保证参照完整性


视图
1.命名的虚表,没有实际的物理存储
   视图也可用于隔离基本表,起到一个安全层的作用
2.也可以对视图执行更新操作,应用到基本表上
3.MYSQL不支持物化视图,只能通过触发器实现类似视图功能;



分区表
1.MYSQL支持水平分区,不支持垂直分区
   同时,只能是局部分区索引(一个分区中既有数据也有索引), 还不支持全局分区
2.分区主要用于数据库高可用性的管理
3.支持以下几种类型的分区:
1.RANGE分区:按列值所属连续区间来分区
2.LIST分区:离散的值来分区
3.HASH分区:自定义的表达式的返回值来分区  => 均匀分布到各分区中
4.KEY分区:数据库提供的函数来分区
5.COLUMNS分区:可使用非整数来分区

3.使用 EXPLAIN PARTITIONS命令查看
mysql root@[localhost:mysql3306.sock carddb_11000] > explain partitions select * from t_account limit 10\G;
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t_account
   partitions: NULL
=>分区修剪可提升查询效率

4.分区和性能
OLAP应用中,分区可以很好地提升查询的性能
OLTP应用中,走主键分区的索引并不会带来性能提升,反而会引起更大开销

非主键查询,数据库会搜索所有的分区,导致更多的IO,影响查询的性能