InnoDB存储引擎--表

1.索引组织表

innodb表是索引组织表,数据即索引,索引即数据

innodb表都有主键(primary key),如果没显示定义,会以第一个定义的非空唯一索引为主键,如果也没有,自动创建一个6字节大小的指针。

2.InnoDB逻辑存储结构

2.1 表空间

image
  • 文件: 共享表空间默认文件为ibdata1;独立表空间文件为表名.ibd。innodb_file_per_table开启独立表空间。
  • 存放内容:使用了独立表空间时,共享表空间存放undo回滚信息、插入缓存索引页、系统事务信息、二次写缓冲等;独立表空间存放该表的数据、索引和插入缓冲bitmap等

2.2 段

段由引擎层管理,一般有三种段:

  • 数据段。B+树的叶子节点
  • 索引段。B+树的非叶子节点
  • 回滚段。

2.3 区

  • 每个区固定1M,由连续的页组成。(16x64 8x128 4x256 2x512)
  • 每个页16K。参数KEY_BLOCK_SIZE可以设置页的大小,压缩页有2K,4K,8K的。
  • 使用独立表空间时,创建的表大小并没有64个连续的页那么大(1M),这是因为在每个段开始时,先用32个页的碎片页,用完才申请64个完整的。

2.4 页

InnoDB磁盘管理的最小单位。也称块。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)

2.5 行

  • InnoDB是面向列的,按行进行存储。一行最多有1023列。
  • 每个页最多存放16K*1024/2 - 200 = 7992行 (每行最少2B)。每行最少存储2行,因为InnoDB索引组织表是B+树结构,小于2行就成链表了。

3.InnoDB行记录格式

3.1 Compact行记录格式

设计目标:高效地存储数据。一个页中行数据越多,性能越高。

image

隐藏列: 事务回滚ID(6字节)和回滚指针列(7字节)。无定主键时有rowid(6字节)。

页内部是用链表结构串连各个行(next_record)

3.2 Redundant行记录格式

Redundant是为了兼容旧版本保留的。

3.3 行溢出数据

  • VARCHAR、BLOB都可能把数据存储在数据页之外。
  • Oracle的VARCHAR2最大4000字节,SQL Server最大8000字节,MySQL的VARCHAR最大存放65535字节,但实际并不能创建65535长的列(实测是65532)。
  • 如果使用多字节编码(GBK,UTF-8),VARCHAR(N)的N是指字符,VARCHAR(65532)也无法达到。
    65535字节是指所有VARCHAR列长度的总和限制。
  • 一个页为16K=16384字节,当一个页不够存储2行数据时,存到未压缩的二进制大对象页(Uncompressed BLOB Page)。测试发现VARCHAR长度阈值为8098:
    CREATE TABLE t(
    a varchar(8098) //超过8098,一个页不够存两条,数据会存到BLOB页
    )

3.4 Compressed和Dynamic行记录格式

image

3.5 CHAR的行存储结构

CHAR(N),N是指字符长度,不同字符集下可能实际存储字节长度不一样。

  • CHAR_LENGTH(列名)函数:字符长度
  • LENGTH(列名)函数:字节长度

可以认为多字节字符集下,CHAR和VARCHAR的存储基本没有区别。

4.InnoDB数据页结构

暂跳过该节

4.1 File Header

4.2 Page Header

4.3 Infimum和Supermum Records

4.4 User Records 和 Free Space

4.5 Page Directory

4.6 File Trailer

4.7 示例

5.Name File Formats机制

解决不同版本下页结构的兼容性问题。

innodb_file_format //文件格式参数

6.约束(constraint)

6.1 数据完整性

关系型数据库自身保证数据的完整性,而文件系统需要应用程序控制。

  • 实体完整性:保证表中有一个主键。InnoDB:Primary Key,Unique Index,触发器
  • 域完整性:保证每列的值满足特定条件。InnoDB:数据类型,外键,触发器,DEFAULT
  • 参照完整性:保证两张表间的关系。InnoDB:Primary Key,Unique Index,外键,DEFAULT,NOT NULL

6.2 约束的创建和查找

创建:建表时定义约束或ALTER TABLE创建约束

CREATE TABLE T(
    ID INT,
    NAME CHAR(10),
    PRIMARY KEY(ID),
    UNIQUE INDEX(NAME)
)

查看:

SELECT TABLE_SCHEMA,
       TABLE_NAME,
       CONSTRAINT_NAME,
       CONSTRAINT_TYPE
  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS

6.3 约束和索引的区别

约束更是一个逻辑概念,用来保证数据完整性。索引是一个数据结构,既有逻辑上的概念,在数据库中还代表着物理存储方式。

6.4 对错误数据的约束

默认允许错误数据的插入。设置SQL_MODE=STRICT_TRANS_TABLES,对输入值进行约束。

6.5 ENUM和SET约束

6.6 触发器与约束

触发器:执行INSERT,DELETE,UPDATE前或后调用SQL或存储过程。一个表最多6个触发器,增删改的前和后。

//SUPER权限用户可以执行
CREATE 
[DEFINER = {user | CURRENT_USER}]
TRIGGER trigger_name BEFORE|AFTER INSERT|UPDATE|DELETE
ON tbl_name FOR EACH ROW trigger_stmt 
//MYSQL支持按每行触发,不像DB2的FOR EACH STATEMENT

6.7 外键约束

7.视图

视图(view)是虚表,由一个查询SQL定义,可以当表使用,无物理存储。

7.1 视图的作用

抽象装置,无需关心基表结构进行查改。起到一个安全层的作用。

SELECT *FROM INFORMATION_SCHEMA.VIEWS

7.2 物化视图

Oracle支持物化视图:存储查询结果到磁盘?需要时直接取。

Oracle物化视图创建方式:

  • BUILD IMMEDIATE。创建物化视图时就生成数据
  • BUILD DEFERRED。根据需要再生成数据
    物化视图的刷新:基表发生DML时,物化视图如何进行同步。

刷新模式:ON DEMAND(需要时),ON COMMIT(提交时)

刷新方法:FAST(增量)
COMPLETE(完全)
FORCE(增量,不行就完全)
NEVER(不刷新)

MySQL不支持物化视图,总是虚拟的。只能通过一些其他机制实现,如触发器。

8.分区表

8.1 分区概述

  • 分区功能不是在存储引擎层实现,是在数据库层实现,但有的存储引擎不支持分区。
  • MySQL支持水平分区(不同行在不同物理文件),不支持垂直分区(不同列在不同物理文件)。一张表对应三个文件:frm(表结构) myd(表数据)myi(表索引)
  • MSQL分区是局部分区索引(分区中存放数据和索引),而全局分区的所有数据索引是存在一个对象中。

分区的好处

存储更大数据。方便按分区的删除。能过滤分区的查询得到优化。SUM(),COUNT()等可以并行处理,最后汇总。提示吞吐量。

分区表的限制

  • 一个表最多只能有1024个分区
  • 分区表中无法使用外键约束。
  • 如果表有主键、唯一索引,分区列必须是索引的一部分。如果没主键、唯一索引,可以指定任意列为分区列。

8.2 RANGE分区

  • RANGE分区主要用于日期列的分区。
  • 范围必须连续但是不重叠。
  • 如果没有 LESS THAN MAXVALUE的分区,插入范围外的列值会报错。
  • 5.5版本COLUMNS关键字,可支持非整数和多列

根据数值范围

partition by range(id)(
    //partition 分区名称 values less than ()
    partition p0 values less than (1000), 
    partition p1 values less than maxvalue
);

根据TIMESTAMP范围

partition by range(unix_timestamp(timestamp_column))(
  partition p0 values less than (unix_timestamp('2008-01-01 00:00:00')),
  partition p1 values less than maxvalue
);

根据DATE、DATETIME范围

partition by range columns(date_column)(
  partition p0 values less than ('1970-01-01'),
  partition p1 values less than maxvalue
);

根据多列范围

partition by range columns(a,b)(
  partition p0 values less than (0,10),
  partition p1 values less than (maxvalue, maxvlaue)
);

8.3 LIST分区

  • 插入列表外的列值会报错
  • 5.5版本COLUMNS关键字,可支持非整数和多列

8.4 HASH分区

  • 只能整数或返回整数的表达式。根据整数对分区数取模。
partition by hash(id)
partitions 4; //没指定时默认1
  • 表达式函数越接近线性越有利于均匀分布。y=nx,n为非零常数
  • Hash分表扩展性差。MYSQL提供了线性Hash分区,使用线性的2的幂运算法则,而不是取模。类似一致性hash。
partition by linear hash(id)
partitions 6;

线性Hash

比如分区数量6,取比6大的2的幂V=8=2^3。

决定该行存到哪个分区N:

//即表达式值与111做与运算(取幂-1就是为了获取最接近的111+)
//保留f(column)的后三位
//这样扩展删除时,不用重新映射不相关分区的?
N = f(column) & (V-1) // V-1=7=111
//如果算出来目标分区大于等于分区数量6,再进行计算:
V=CEILING(V/2) //降幂 向上取舍 再与运算 相当于去掉2进制最高位
N = N & (V-1) 

线性哈希分区的优点在于增加、删除、合并和拆分分区将变得更加快捷,有利于处理含有极其大量(1000G)数据的表。它的缺点在于,与使用常规HASH分区得到的数据分布相比,各个分区间数据的分布不大可能均衡。

8.5 KEY分区

与HASH分区类似,也有线性key分区方法。

MySQL 簇(Cluster)使用函数MD5()来实现KEY分区

//表存在主键或唯一索引时可省略Key括号内的列名,Mysql将按照主键-唯一索引的顺序选择
//当找不到唯一索引时报错
partition by linear key(id) 
partitions 4;

8.6 子分区

每个分区必须有相同数量的子分区

CREATE TABLE ts (id INT, purchased DATE)
    PARTITION BY RANGE(YEAR(purchased))
    SUBPARTITION BY HASH(TO_DAYS(purchased))
    SUBPARTITIONS 2
    (
        PARTITION p0 VALUES LESS THAN (1990),
        PARTITION p1 VALUES LESS THAN (2000),
        PARTITION p2 VALUES LESS THAN MAXVALUE
    )

8.7 对NULL值的处理

NULL插入RANGE和LIST时,会被视为0

8.8 分区性能

  • 数据库应用分为两类:一类是OLTP(在线事务处理),如博客、电子商务、网游等;另一类是OLAP(在线分析处理),如数据仓库、数据集市。
  • 对于OLAP的应用,分区的确可以很好的提高查询性能,因为OLAP应用的大多数查询需要频繁的扫描一张很大的表,如果进行分区则只需要扫描相应的部分即可。
  • 而对于OLTP应用一般情况下不可能获取一张大表中10%的数据,大部分都是通过索引返回若干记录。对于一张大表,一般的B+树需要2~3次磁盘IO。举个列子,一张数据量为1000万行的表B+树高度为3,将他分为10个区,100万行的B+树高度是2。单独对于Key索引的查询在基于分区设计的情况下查询开销为2次IO,而原表设计需要2到3次IO。而如果对于其他列索引的查询就可能需要10 * 2 = 20次IO。分区查询耗时将远远大于没有进行分区设计数据表的查询耗时。

8.9 在表和分区间交换数据

ALTER TABLE ... EXCHANGE PARTITION

使用条件和注意事项:

  • 表结构相同,非分区表不能有分区(...废话?)
  • 非分区表中数据必须在分区定义内(如列表分区只有A,B,C,是不能插入D)
  • 不能还有外键,或其他表对该表有外键
  • 需要ALTER、INSERT、CREATE和DROP权限
  • 不会触发两表上的触发器。
  • AUTO_INCREMENT列会被重置。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342