mysql format row_MySQL之InnoDB存储引擎:Row Format行格式

MySQL下用的比较多、比较广的存储引擎就属InnoDB。这里我们来介绍下InnoDB存储引擎下数据记录的存储格式——Row Format行格式

基本操作

在MySQL中,所谓Row Format行格式是指数据记录(或者称之为行)在磁盘中的物理存储方式。具体地,对于InnoDB存储引擎而言,常见的行格式类型有Compact、Redundant、Dynamic和Compressed

设置、修改行格式信息

在创建、修改数据表的时候,可以显式地指定row format行格式。SQL语句语法如下

-- 创建数据表时,显示指定行格式CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称;

-- 创建数据表时,修改行格式ALTER TABLE 表名 ROW_FORMAT=行格式名称;

与此同时,如果需要查看某数据表的行格式,可通过如下语句实现

show table status from 数据库名 like '';

演示示例

下面通过一个示例来验证上述语句的使用及效果。在test1数据库中创建一张名为task2的数据表,并指定行格式的类型为compact

use test1;

-- 指定行格式create table task2

(

idx int auto_increment,

primary key (idx)

) row_format = compact;

-- 查看行格式show table status from test1 like 'task2';

从下图可以看出表的行格式类型被设置为compact

然后再将该表的行格式类型修改为dynamic

-- 修改行格式alter table task2

row_format = dynamic;

-- 查看行格式show table status from test1 like 'task2';

从下图可以看出表的行格式类型已被修改为dynamic

Compact 行格式

Compact行格式在MySQL 5.0中被引入,其目标是为了更高效的存储数据记录。在该格式下,一条数据记录的组成部分如下所示。其大体分为两部分——记录的额外信息、记录的数据内容。后者比较好理解,其即是我们存储到数据库的各列(字段)数据值。而前者则是MySQL为了更好描述该条记录而添加的额外信息

变长字段的长度列表

由于MySQL支持变长的数据类型(如VARCHAR等),故对于该类型而言,不仅需要存储该字段的实际数据,还需要额外存储该数据的长度信息(即占用的字节数)。而这就是变长字段的长度列表的用途。而一个变长字段的数据长度信息可能会使用1~2个字节来进行表示,具体地,如果某变长类型的字段 允许存储的最大字节数不超过255个字节,显然长度信息只需要一个字节表示即可;而当 某变长类型的字段允许存储的最大字节数超过255个字节时,这个时候就需要分情况讨论了:该字段数据实际使用的字节数不超过127个字节:依然只使用一个字节表示

该字段数据实际使用的字节数超过127个字节:使用两个字节表示

对于该变长类型字段其允许存储的最大字节数该如何计算呢?这里我们以常见的VARCHAR(M)类型为例进行说明,我们知道该类型表示最多能存储M个字符。那一个字符占多少个字节呢?这就和我们之前所说的字符集有关了。我们知道字符集的Maxlen列信息,表示该字符集中一个字符最多需要几个字节来表示。比如utf8字符集下Maxlen列值为3、ascii字符集下Maxlen列值为1。故对于VARHCAR(M)来说,M x Maxlen 即为在某字符集下该变长类型字段允许存储的最大字节数

当然有人可能会问?MySQL在读记录的时候,如果发现某字段的M x Maxlen值超过255个字节了,那么它在读取记录的变长字段的长度列表时,是将该字节作为单独的字段长度信息还是作为半个的字段长度信息呢?即是读一个字节还是读两个字节。其实这个问题很简单,因为数值127写成二进制为 0111 1111。所以如果该字节的第一位为0,则该字节就是一个单独的字段长度信息;反之为1,则说明该字段只是半个的字段长度信息。即将字节的第一位作为标志位

Note

1. 变长字段的长度列表不存储值为非NULL的长度信息

对于变长类型的字段而言,如果某记录下该字段的值为NULL,则变长字段的长度列表不会存储该字节的信息。因为是特殊值,会通过下面即将说明的NULL标志位进行存储

2. 变长字段的长度列表不是一定存在的

一方面,表中可能没有变长类型的字段;另一方面,如果该记录中所有的变长字段值均为NULL,根据第一点易知,此时变长字段的长度列表同样也没有存在的必要

3. 变长字段的长度列表中各字段长度信息是按列的顺序逆序排列的

这里我们假设有一张ascii字符集的数据表,其各字段依次为vf1,vf2,vf3,f4。其中vf1,vf2,vf3字段均为变长类型的字段。假设有一条记录其在各字段的值依次为:"a",NULL,"ccc",99。即变长字段vf1的长度为1,变长字段vf3的长度为3。则该记录的变长字段的长度列表内容为:0x03(即十进制的3)0x01(即十进制的1)

4. char类型字段的长度信息是否需要存储在 变长字段的长度列表 中取决于其所使用的字符集是否为变长字符集

MySQL中char(M)类型的字段表示该字段最多可以存储M个字符。对于定长字符集(如ascii字符集)而言,compact行格式下存储该字段所占有的空间固定为M x Maxlen个字节。但是对于变长字符集而言情况就大不一样了,例如utf8字符集,其存储M个字符所需的空间为M~3M个字节。在compact行格式下,char类型字段会由于使用变长字符集而导致其所占的字节数(即长度信息)不定,故此时char类型的数据同样也需要在变长字段的长度列表中存储其长度信息

NULL值标志位

对于记录中的特殊值NULL而言,如果直接存储到记录的数据内容部分则显得比较浪费空间,故这里使用位向量进行存储。如果某字段为主键或被NOT NULL所修饰,则其值自然不允许为NULL。故位向量中不是直接包含了所有字段,而是排除了值不能为NULL的字段,此举进一步减小了占用空间。具体地,位向量中某一位为1,则表明该列值为NULL;否则如果该位值为0,则表明值不为NULL

值得一提的是,首先位向量中代表的列同样是按照列的顺序逆序排列的,其次对于位向量不足一个字节的部分,高位需补0,即按照一字节对齐。假设这里有一张数据表,其字段定义分别为f1,f2,f3,f4。其中f2字段为主键,其余字段均可以为NULL,则有一条记录其值依次为:"Amy",1,NULL,2,则该记录的NULL值标志位内容如下所示

NoteNULL值标志位不是一定存在的

如果某条记录所有字段均不允许为NULL,则显然用于管理记录字段为NULL值的NULL值标志位在该条记录中是没有必要的,即不存在

记录头信息

记录头信息用于描述该条记录,其固定为5个字节,即40位。其定义如下预留位1、2:暂未使用

delete_mask:当前记录被删除的标志位

min_rec_mask:B+树的每层非叶子节点中的最小记录的标志位

n_owned:当前记录拥有的记录数

heap_no:当前记录在记录堆中的位置

record_type:当前记录类型。具体地,0: 普通记录;1: B+树非叶子节点记录(即所谓的目录项记录);2: 最小记录;3: 最大记录

next_record:下一条记录的相对位置

记录的数据内容

记录的数据内容,通常来说就是我们日常开发、使用过程中需存储的记录的数据内容。但其实,MySQL对于我们所定义的数据表,还会默认的插入一些其他列(字段),即所谓的隐藏列。其字段定义说明如下DB_ROW_ID:该字段占6个字节,用于标识一条记录

DB_TRX_ID:该字段占6个字节,其值为事务ID

DB_ROLL_PTR:该字段占7个字节,其值为回滚指针

上述3个字段,除了DB_ROW_ID字段,其余两个字段均一定会被添加到数据表中的。一般地,当用户未指定数据表的主键时,MySQL会选择非NULL的Unique键作为主键。而如果非NULL的Unique键也没有的话,这个时候MySQL才会添加向数据表添加DB_ROW_ID字段用来作为主键。当然上述隐藏列的3个字段的值是由MySQL自动生成、存储的

Note

1. 值为NULL的记录不会存储于此

记录的数据内容不包括字段值为NULL的数据内容。前文已经提到,对于记录中某字段为NULL值的信息已经体现在NULL值标志位中了,故此处将不再重复存储以节省空间

2. char类型字段的存储方式

值得一提的是,对于变长字符集下的char(M)类型字段而言,出于存储优化的角度考虑,compact行格式要求存储该字段的值时至少占用M个字节,字段值所占字节数不足时则使用 空格字符(空格字符在ascii字符集下为0x20) 填充。比如某字段类型为char(10),其使用utf8字符集,即使某条记录该字段值为"abc",只使用了3个字节。但是在存储"abc"时,依然会通过在其后填充若干个空格字符的方式使其达到占用10个字节的空间来进行存储。此举目的其实也很简单,当该条记录下次需要更新时,如果新值使用的空间不超过10个字节时,则可以直接在此条记录处进行更新而无需重新分配一个新的记录空间,从而导致原有的记录空间成为碎片。当然在读值的时候会把填充的空格字符移除掉

Redundant 行格式

Redundant作为MySQL 5.0之前使用的一种行格式,其示意图如下所示,可以看到其与compact行格式在结构上大体还是比较相似的。这里主要来介绍下其与compact行格式不同之处

字段长度偏移列表

在Redundant行格式下,其通过字段长度偏移列表存储记录中所有列(包括隐藏列)的长度信息。首先计算记录中各字段的长度信息,然后再顺序计算长度的累计值,最后再按数据表各字段的顺序逆序排列,即为实际存储的字段长度偏移列表。反过来如果期望获取记录中某字段的长度信息,只需计算两个相邻长度累计值的差值即可

具体地,字段长度偏移列表中的各偏移量所占空间要么均为1个字节,要么均为2个字节。那么实际存储记录时,到底是使用1个字节还是使用2个字节来存储字段长度偏移列表呢?其实在该格式下,策略比较简单。若记录的整个数据内容部分(包括隐藏列)所占用的空间不超过127(0x7F)个字节,则该记录的字段长度偏移列表的各偏移量自然只需使用1个字节即可表示,毕竟所有列长度值加起来也不超过127,那么各个列所对应的偏移量自然也不会超过127了;反之如果超过127个字节但不超过32767(0x7FFF)个字节,则会使用2个字节来表示各偏移量。与此同时,该记录会通过记录头信息的1byte_offs_flag属性来表明该记录各偏移量的字节数,以便读取记录的时候方便解析

Note偏移量包含NULL值标志

一方面,通过对比compact与redundant的结构图,可以发现在compact行格式下其没有NULL值列表;另一方面,偏移量在使用1、2个字节表示时,其能表示的最大值分别为0x7F、0x7FFF,即偏移量的第一位实际上是没有使用的。其实原因就在于,对于各列偏移量的第一位而言,其用于标识该记录下相应列是否为NULL值。如果是NULL值,则该位为1;反之,则为0

记录头信息

记录头信息用于描述该条记录,其固定为6个字节,即48位。其定义如下预留位1、2:暂未使用

delete_mask:当前记录被删除的标志位

min_rec_mask:B+树的每层非叶子节点中的最小记录的标志位

n_owned:当前记录拥有的记录数

heap_no:当前记录在记录堆中的位置

n_field:表示记录中列的数量

1byte_offs_flag:标识字段长度偏移列表中各列的偏移量使用的字节数。0:意为每个偏移量均使用2个字节表示;1:意为每个偏移量均使用1个字节表示

next_record:下一条记录的相对位置

记录的数据内容

在redundant行格式下,其与compact行格式一样,同样有隐藏列的情况。这里就不再赘述了。这里我们就不同的地方进行一些介绍。前面我们提到在compact行格式下,对于char(M)类型的字段数据在定长字符集、变长字符集下的存储方式是有差异的,相对而言还是比较复杂;而在redundant行格式下,无论是使用变长字符集还是使用定长字符集,char(M)类型的字段总是占用M x Maxlen个字节的空间,字段值所占空间的字节数不足则同样会使用 空格字符(空格字符在ascii字符集下为0x20) 进行填充

上文提到compact行格式下,字段为NULL值是不会在记录的数据内容中占用存储空间,冗余存储的;而在redundant行格式下,对于字段为NULL值在记录的数据内容部分的存储则略有不同如果值为NULL的字段类型为变长数据类型,其同样不会在记录的数据内容中占用任何空间来进行存储的

如果值为NULL的字段类型为定长数据类型,其使用0x00来填充该字段所需占用的空间。例如char(10)类型的字段,在ascii、utf8字符集中其Maxlen值分别为1、3。即该字段在数据内容部分会分别占用的10、30个字节。故当该字段为NULL值时,会使用0x00来填充这10、30个字节的位置

行溢出

众所周知,InnoDB存储引擎中内存与硬盘交互的基本单位是页,一般地页大小为16KB。MySQL规定一个页中至少需要存放两条记录。而所谓的行溢出是指:当某个记录的某个字段(varchar、text、blob等类型)的值长度过长、数据量过大,会导致一个页中放不下一条记录,为此在compact、redundant行格式中,如果该记录某字段中数据量过多时,则在该记录的数据内容的相应字段处只存储该字段值前768个字节的数据和一个指向存储剩余数据的其他页(即所谓的溢出页)的地址,该地址通常占用20个字节

Dynamic、Compressed行格式

对于Dynamic、Compressed行格式而言,其和compact行格式比较相似。不同的在于,对待处理行溢出的处理及策略,Dynamic、Compressed行格式会把记录中数据量过大的字段值全部存储到溢出页中,而不会在该记录的数据内容的相应字段处存储该字段值前768个字节的数据了。而compressed相比较dynamic行格式来说,前者会使用压缩算法对所有页面(自然也包括溢出页)进行压缩以减少存储占用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DirectX API 编程起步 #01 项目设置

目录: DirectX API 编程起步 #02 窗口的诞生 DirectX API 编程起步 #02 创建3D世界 这里记录了我从零开始学习使用 DirectX API 的过程。 参考教程:rastertek -> DirectX 11 Tutorials 准备工作 1)首先我们要有一套能写代码的软件&#…

centos5.8安装mysql5.3_CentOS 5.8 64位 源码安装mysql5.5.28

全新以最小化包安装了64位的CentOS5.8系统mysql5.5数据库v5.5.28地址:http://cdn.mysql.com/Downloads/MySQL-5.5/mysql-5.5.28.tar.gzmysql从5.5版本开始,不再使用./configure编译,而是使用cmake编译器我的mysql目录配置如下:安装…

LeetCode 2016. 增量元素之间的最大差值

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;该数组的大小为 n &#xff0c;请你计算 nums[j] - nums[i] 能求得的 最大差值 &#xff0c;其中 0 < i < j < n 且 nums[i] < nums[j] 。 返回 最大差值 。如果不存在满足要求…

LeetCode 2017. 网格游戏(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的二维数组 grid &#xff0c;数组大小为 2 x n &#xff0c;其中 grid[r][c] 表示矩阵中 (r, c) 位置上的点数。 现在有两个机器人正在矩阵上参与一场游戏。 两个机器人初始位置都是 (0, 0) &#xff0c;目标位置是 (1,…

mysql ngram_MySQL ngram全文解析器

本教程将向您展示如何使用MySQL ngram全文解析器来支持中文&#xff0c;日文&#xff0c;韩文等表意语言的全文搜索。MySQL ngram全文解析器简介MySQL内置的全文解析器使用空格确定单词的开始和结束。当涉及汉语&#xff0c;日语或韩语等表意语言语言时&#xff0c;这是一个限制…

手机号、姓名、邮箱等合法性验证方法

//邮箱 (BOOL) validateEmail:(NSString *)email{NSString *emailRegex "\\w[a-zA-Z_]?\\.[a-zA-Z]{2,6}";NSPredicate *emailTest [NSPredicate predicateWithFormat:"SELF MATCHES %", emailRegex];return [emailTest evaluateWithObject:email];}//…

zabbix设置mysql登陆免报警_zabbix3.0 监控mysql服务免用户名密码登录的有关问题故障处理详细过程_mysql...

zabbix3.0 监控mysql服务免用户名密码登录的问题故障处理详细过程1&#xff0c;My.cnf中用户名密码无效在azure云上面&#xff0c;使用Zabbix监控mysql中&#xff0c;发现在/usr/local/mysql/my.cnf里面设置的默认用户名密码无效&#xff0c;出不来数据&#xff0c;而且在zabbi…

LeetCode 2018. 判断单词是否能放入填字游戏内(模拟)

文章目录1. 题目2. 解题1. 题目 给你一个 m x n 的矩阵 board &#xff0c;它代表一个填字游戏 当前 的状态。 填字游戏格子中包含小写英文字母&#xff08;已填入的单词&#xff09;&#xff0c;表示 空格 的 和表示 障碍 格子的 # 。 如果满足以下条件&#xff0c;那么我…

链表的相关操作

#include<iostream> using namespace std; struct node {int data;node *next; }; //链表的建立&#xff0c;创建有n个结点的链表 node *create(int n) {node *headNULL;node *pNULL;headnew node();phead;cin>>p->data;node *q;while(--n){qnew node();cin>…

qt优点

&#xff08;1&#xff09;优良的跨平台特性。   Qt支持下列操作系统&#xff1a;Microsoft Windows 95/98、Microsoft Windows NT、Linux、Solaris、SunOS、HP&#xff0d;UX、Digital UNIX &#xff08;OSF/1、Tru64&#xff09;、Irix、FreeBSD、BSD/OS、SCO、AIX、OS390和…

LeetCode 2022. 将一维数组转变成二维数组

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n 。 你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。 original 中下标从 0 到 n - 1 &#xff08;都 包含 &#xff09;的元素构成二维数组的第一行&#xf…

mysql系统自带示例数据库_MySQL系统自带的数据库information schema

information_schema数据库是MySQL系统自带的数据库&#xff0c;它提供了数据库元数据的访问方式。感觉information_schema就像是MySQL实例的一个百科全书&#xff0c;记录了数据库当中大部分我们需要了结的信息&#xff0c;比如字符集&#xff0c;权限相关&#xff0c;数据库实…

Json对象与Json字符串互转(4种转换方式)

最近有用到php的json字符串要转成js对象&#xff0c;以前一直用jq或者eval&#xff0c;又发现了其他的方法&#xff0c;记录下. 1>jQuery插件支持的转换方式&#xff1a; 复制代码代码如下:$.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成jso…

LeetCode 2023. 连接后等于目标字符串的字符串对

文章目录1. 题目2. 解题1. 题目 给你一个 数字 字符串数组 nums 和一个 数字 字符串 target &#xff0c;请你返回 nums[i] nums[j] &#xff08;两个字符串连接&#xff09;结果等于 target 的下标 (i, j) &#xff08;需满足 i ! j&#xff09;的数目。 示例 1&#xff1a…

What day is that day?(快速幂,打表找周期,或者求通项公式)

有些题怎么都解不出来&#xff0c;这时候可以打表&#xff0c;找规律&#xff0c;求通项公式等&#xff0c;这些方法让人拍手叫绝&#xff0c;真不错…… Description Its Saturday today, what day is it after 11 22 33 ... NN days? Input There are multiple test cas…

mysql中数据定义语言_SQL数据定义语言(DDL)

数据库模式定义语言DDL(DataDefinition Language)&#xff0c;是用于描述数据库中要存储的现实世界实体的语言。一个数据库模式包含该数据库中所有实体的描述定义。这些定义包括结构定义、操作方法定义等。DDL描述的模式&#xff0c;必须由计算机软件进行编译&#xff0c;转换为…

瞎搞

declare a int,b int,c int set a (select top 1 a from Table_1 ) set b (select top 1 b from Table_1 ) set c (select top 1 c from Table_1 ) if(a>b and a>c) beginprint(a的值最大)endif(b>a and b>c) beginprint(b的值最大)endif(c>a and c>b) be…

db2 脚本运行错误返回错误原因_电脑运行错误代码大全,遇到报错请自己对照断电原因所在吧...

电脑在运行的时候&#xff0c;会出现一些代码&#xff0c;软件安装不上啊或电脑使用中蓝屏啊出现的代码&#xff0c;每一次出现问题电脑都会以代码的形式反馈&#xff0c;我们就可以凭借错误代码来判断故障源。小编整理了一些常出现的错误代码和问题分享给大家&#xff0c;希望…

LeetCode 2028. 找出缺失的观测数据

文章目录1. 题目2. 解题1. 题目 现有一份 n m 次投掷单个 六面 骰子的观测数据&#xff0c;骰子的每个面从 1 到 6 编号。 观测数据中缺失了 n 份&#xff0c;你手上只拿到剩余 m 次投掷的数据。 幸好你有之前计算过的这 n m 次投掷数据的 平均值 。 给你一个长度为 m 的整…

Sqlite学习笔记(五)SQLite封锁机制

概述 SQLite虽然是一个轻量的嵌入式数据库&#xff0c;但这并不影响它支持事务。所谓支持事务&#xff0c;即需要在并发环境下&#xff0c;保持事务的ACID特性。事务的原子性&#xff0c;隔离性都需要通过并发控制来保证。那么Sqlite的并发控制是怎样的&#xff0c;如何实现&am…