引言

我们都知道,mysql中的索引,事务,锁等都是作为开发人员要重点掌握的知识面,但要想掌握理解好这些知识却并非易事。

其中原因之一就是这些概念都过于抽象,事实上如果都不懂mysql数据是以一种怎样结构存储的,就直接去学习索引等模块,如此理解起来自然是事倍功半的。

因此本文的目的有两点:

  • 揭露数据存储的格式
  • 说明Mysql是如何读取数据

在正文开始之前要先明确一点,Mysql有很多存储引擎,不同的存储引擎对于数据的存放格式是不一样的,目前Mysql的存储引擎默认是InnoDB,因此本文主要以InnoDB的角度去讲解。

行格式

我们经常会说往表中插入一条数据,实际上InnoDB数据存储的基本单位其实就是一条数据。这行数据在磁盘上存储的格式就叫做行格式。

InnoDB设计了4种行格式,分别是Compact、Redundant、Dynamic和Compressed行格式,接下来我们会重点讲解Compact,同时它也是最常用的行格式。

COMPACT行格式

直接先看一张图:

看图说话,Compact行格式可以分为两大块:

  • 额外信息
  • 真实数据

所谓真实数据自然就是我们要存放的值,而额外信息存储的是对这行记录的一些描述。

其中额外信息包括变长字段长度列表,NULL值列表,记录头信息。

变长字段长度列表

在Mysql有一些数据类型,比如VARCHAR(M)、TEXT等,它们是属于支持变长的数据类型,实际使用的字节数是不固定的。所以Mysql需要把这些类型的列实际使用了多少字节数给记录下来,记录的地方就是在变长字段长度列表

在Compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放。

举个例子,我们创建个表

CREATE TABLE record_format_demo (
-> c1 VARCHAR(10),
-> c2 VARCHAR(10) NOT NULL,
-> c3 CHAR(10),
-> c4 VARCHAR(10)
-> )

可以看到c1,c2,c4列都是变长的,此时我们插入一条数据

INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', 'cc', 'd')

我们假定内容占用的字节为

列名 存储内容 占用字节(十六进制表示)
c1 'aaaa' 0x04
c2 'bbb' 0x03
c4 'd' 0x01

所以这条记录的存储格式就为

可以看到变长字段长度列表是逆序(c4->c2->c1)排放的。

因此要计算1个变长字段到底占用了多少空间要计算两部分:

  • 真实数据占用的空间
  • 记录真实数据占用空间所使用的字节数

以列C1为例:

占用字节数='aaaa'(4字节)+ '0x04'(1字节)

NULL值列表

我们知道表中的某些列可能存储NULL值,如果把这些NULL值都放到记录的真实数据中存储会很占地方,所以Compact行格式把这些值为NULL的列统一管理起来,存储到NULL值列表中。

每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列,,二进制位表示的意义如下:

  • 二进制位的值为1时,代表该列的值为NULL。
  • 二进制位的值为0时,代表该列的值不为NULL。

我们在来插入一条记录

INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', null, null)

因此这条记录的null值列表就是:

行格式就是:

可以看到二进制110就是十进制的6.

记录头信息

记录头信息,它是由固定的5个字节组成。5个字节也就是40个二进制位,不同的位代表不同的意思。本文不会细讲,在后续的文章中有涉及再说讲解。

真实数据

真实数据除了c1、c2、c3、c4这几个我们自己定义的列的数据以外,其实MySQL会为每个记录默认的添加一些列(也称为隐藏列),具体的列如下:

transaction_id和roll_pointer的作用将会在后面提及。

而row_id这个列只有在表没有自定义主键并且Unique键的情况下才会添加,作为表的主键。

以上就是InnoDb存储数据的行格式,下一篇文章将会介绍页的概念。

Mysql综述(1)数据是如何读存的的更多相关文章

  1. Mysql综述--数据是如何读存的?(2)

    页的结构 页是一种InnoDB管理存储空间的基本单位,它一般大小在16kb左右.实际上存在着许多不同类型的页,我们这次主要介绍的页是用来存储数据的,也叫做索引页. 接下来看看索引页的结构图: 比较重要 ...

  2. CentOS6 更改Mysql数据库的数据存放位置

    mysql使用yum安装时,默认的数据是存储在/var/lib/mysql下.一般情况下,为了数据的安全性,建议将mysql数据库的数据文件存储在系统的第二块磁盘上的目录下可以按照以下步骤进行操作: ...

  3. php查询mysql返回大量数据结果集导致内存溢出的解决方法

    web开发中如果遇到php查询mysql返回大量数据导致内存溢出.或者内存不够用的情况那就需要看下MySQL C API的关联,那么究竟是什么导致php查询mysql返回大量数据时内存不够用情况? 答 ...

  4. 大数据学习day33----spark13-----1.两种方式管理偏移量并将偏移量写入redis 2. MySQL事务的测试 3.利用MySQL事务实现数据统计的ExactlyOnce(sql语句中出现相同key时如何进行累加(此处时出现相同的单词))4 将数据写入kafka

    1.两种方式管理偏移量并将偏移量写入redis (1)第一种:rdd的形式 一般是使用这种直连的方式,但其缺点是没法调用一些更加高级的api,如窗口操作.如果想更加精确的控制偏移量,就使用这种方式 代 ...

  5. [转] MySql 优化 大数据优化

    一.我们可以且应该优化什么? 硬件 操作系统/软件库 SQL服务器(设置和查询) 应用编程接口(API) 应用程序 ------------------------------------------ ...

  6. 快速的mysql导入导出数据(load data和outfile)

    1.load data: ***实际应用:把日志生成的xls文件load到MySQL中: mysql_cmd = "iconv -c -f utf-8 -t gbk ./data/al_ve ...

  7. redis作为mysql的缓存服务器(读写分离,通过mysql触发器实现数据同步)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  8. Ubuntu系统下MySQL读取文件数据ERROR解决

    博文链接:http://haoyuanliu.github.io/2016/04/29/mysql/ 对,我是来骗访问量的!O(∩_∩)O~~ 在使用MySQL进行文件数据读取的时候,在终端敲入命令行 ...

  9. 用python批量向数据库(MySQL)中导入数据

    用python批量向数据库(MySQL)中导入数据 现有数十万条数据,如下的经过打乱处理过的数据进行导入 数据库内部的表格的数据格式如下与下面的表格结构相同 Current database: pyt ...

随机推荐

  1. 开发利器JRebel部署SpringBoot项目

    不要以为年纪轻轻就跌倒了人生谷底,未来还有更大的下降空间等着你. idea下载和安装JRebel 激活JRebel 访问https://my.jrebel.com/ 使用facebook或twitte ...

  2. 关于Elasticsearch文档的描述以及如何操作文档的详细总结

    文档 什么是文档 在大多数应用中,多数实体或对象可以被序列化为包含键值对的 JSON 对象. 一个 键 可以是一个字段或字段的名称,一个 值 可以是一个字符串,一个数字,一个布尔值, 另一个对象,一些 ...

  3. apache ignite系列(四):持久化

    ignite持久化与固化内存 1.持久化的机制 ignite持久化的关键点如下: ignite持久化可防止内存溢出导致数据丢失的情况: 持久化可以定制化配置,按需持久化; 持久化能解决在大量缓存数据情 ...

  4. Django--路由层、视图层、模版层

    路由层: 路由匹配 url(正则表达式,视图函数内存地址) 只要正则匹配到了内容,就不再往下匹配,而是直接运行后面的视图函数 匹配首页) url(r'^&', home) 匹配尾页 url(r ...

  5. Python集训营45天—Day04 (函数)

    目录 1. 函数介绍 2. 函数的参数 3. 模块与函数 4. 递归函数 5. 匿名函数 6. 多返回值 python 的学习已经进入到第四天,前面几章我们已经学会了基本的变量操作,以及分支结构和循环 ...

  6. MOOC C++笔记(三):类和对象提高

    第三周:类和对象提高 this指针 作用 this指针作用就是指向成员函数所作用的对象. 非静态成员函数中可以直接使用this来代表指向该函数作用的指针. 成员函数中默认有一个this指针指向当前对象 ...

  7. Spring——依赖注入(DI)详解

    声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...

  8. 基于docker构建测试环境

    目录 0x01介绍 0x02 镜像基本操作 0x03 容器基本操作 0x04 容器的修改与保存 0x05 使用Dockerfile定制镜像 0x01介绍 Docker 是一个开源的应用容器引擎,基于 ...

  9. embedding技术

    目录 word2vec 负采样 目标函数 反向梯度 层次softmax NPLM的目标函数和反向梯度 目标函数 反向梯度 GNN(图神经网络) deepwalk node2vec 附录 word2ve ...

  10. Android Studio [RecyclerView/列表视图]

    LinearRecyclerViewActivity.java package com.xdw.a122.recyclerview; import android.graphics.Rect; imp ...