精华内容
下载资源
问答
  • word转成html源代码,需要朋友可以看看
  • 文件存储格式

    2020-06-24 19:59:42
    文件存储格式:文件存储格式是数据在磁盘上的组织方式,直接决定了数据存取效率以及被上层分布式计算集成的容易程度。 1.2 常见存储格式 创建的存储格式包括 行式存储 和 列式存储 两种: 行式存储 以 文本格式...

    目录

     

    一、前言

    1.1 概述

    1.2 常见存储格式

    1.3 行列存储数据组织方式

    1.4 行列存储优缺点对比

    1.5 Hadoop 的 数据存储格式实现

    二、行存储格式

    2.1 文本格式(Text File)

    2.2 Sequence File

    三、列式存储格式

    3.1 ORC 文件

    3.2 Parquet 文件

    3.3 CarbonData 文件

    3.4 ORC、Parquet 和 CarbonData 对比


    一、前言

    1.1 概述

    文件存储格式:文件存储格式是数据在磁盘上的组织方式,直接决定了数据存取效率以及被上层分布式计算集成的容易程度。

    1.2 常见存储格式

    创建的存储格式包括 行式存储 和 列式存储 两种:

    行式存储 以 文本格式Text File、key/value 二进制存储格式 Sequence File 为典型代表。

    列式存储 以 ORC、Parquet 和 Carbon Data 三种文件格式为代表。

    1.3 行列存储数据组织方式

        数据(每一行由若干列构成)在行存储和列存储系统中组织方式如下图所示。行存储以行为单位进行存储,读写过程是一致的,都是连续读取或写入同一行的所有列;列存储写数据时将数据拆分成列,并以列为单位存储(相同列存储在一起),读数据时,分别读取对应的列,并拼装成行。

    1.4 行列存储优缺点对比

    1.5 Hadoop 的 数据存储格式实现

        大数据应用场景下,通常需要在计算层并行处理文件,为了应对这种场景,Hadoop 将文件读取和写入模块抽象成 InputFormat 和 OutputFormat 组件,其中 InputFormat 可将数据文件逻辑上划分成多个可并行处理的 InputSplit,OutputFormat 可将数据以指定的格式写入输出文件。Hadoop 为常见的数据存储格式分别设计了 InputFormat 和 OutputFormat 实现,以方便像 MapReduce、Spark 等上层计算框架使用。

    二、行存储格式

    2.1 文本格式(Text File)

        文本格式是以文本字符串方式保存数据,具有简单、易查看等优点,是使用最广泛的行式存储格式,几乎所有的编程语言均提供了文本文件的读写编程接口。

    2.2 Sequence File

        Sequence File 是 Hadoop 中提供的简单 key/value 二进制行式存储格式,可用于存储文本格式无法存储的数据,比如二进制对象、图片、视频等。为了方便上层计算框架并行处理,Sequence File 物理存储上是分块的,根据压缩方式不同,Sequence File 存在三种存储格式,具体如下:

    (1)未压缩的 Sequence File

        未压缩的 Sequence File 组织方式如下图所示,由头部开始,顺序跟着一系列record(一条行记录),为了便于对数据分块和按块压缩,每个一定数目的record会写入一个同部位 SyncMark。头部中包含版本、key对应类、value对应类、是否压缩等信息;每条record以 key/value 的形式组织。

    (2)行级压缩的 Sequence File

        行级压缩与未压缩的 Sequence File 类似,如下图所示,区别在于头部加入了压缩相关的信息(压缩标记位置设为true,并记录了压缩器类),而 record 中的value值是经压缩后存储的。

    (3)块级压缩的 Sequence File

        块级压缩的 Sequence File 是以块为单位组织 record 的,如下图所示,在每块数据中,所有 record 的 key 长度、key值,value 长度和 value 值将分别被存放在一起,并一起压缩存储。

    在实际应用时,Sequence File 中的 record 的 value 值可以是普通字符串,也可以是 Java对象,或Thrift、Protobuf 、Avro对象。

    三、列式存储格式

        在实际应用场景中,数据的列数往往非常多(几十列到上百列),而每次处理数据时只用到少数几列,此时采用列式存储是非常合适的。列式存储格式的代表有 ORC(Optimized Row Columnar)、Parquet 和 Carbondata 三种,ORC 前身是 RC File,诞生于 Apache Hive,支持全部的 Hive 类型(比如map、list等),Parquet 是 Google Dremel 中列式存储格式的开源实现,可与 Thrift、Protobuf、Avro等序列化框架使用,CarbonData是华为开源的支持索引的高效列式存储格式,它们均是Apache顶级项目。

    3.1 ORC 文件

        ORC 是专为 Hadoop 设计的字描述的列式存储格式(Apache Hive 0.11版本引入),重点关注提高数据处理系统效率和降低数据存储空间,它支持复杂数据类型、ACID 及 内置索引支持,非常适合质量数据的存储。

    ORC File 由 stripe、footer 和 postscript 三部分构成:

        1> stripe 是数据存储单元,一定数目的行数据组成一个stripe,每个stripe大小约为250MB,stripe是一个逻辑处理单元,可由一个任务单独处理。每个stripe包含索引域、数组域和尾部域三部分,其中索引域记录每列最大值、最小值等信息,数据域以列为单元组织数据,尾部域存储了每列数据在数据域中的位置、编码方式等。

        2> footer 记录了ORC File 文件主体的布局,包括 schema 信息,行总数、每行的统计信息等。

        3> postscript 记录了ORC文件级别的源信息,包括footer长度、ORC版本号、采用的压缩算法等。

    (1)支持复杂数据类型

        ORC 是 Hortonworks 公司为了提高 Hive 处理效率和降低数据存储空间而设计的存储格式,它支持 Hive 所有数据类型,包括 int、string、date 等基本类型,也包括 struct、list、map 和 union 等复杂数据类型,尤其是对复杂数据类型的支持使得ORC能够定义非结构化数据。ORC 以列为单位存储数据,并根据列的类型进行编码,比如对整数列采用变长编码和差值编码,对字符串采用字典编码等,列式存储与数据编码的引入,使得ORC文件可达到很高的压缩比。Hortonworks 技术人员使用 TPC-DS Scala 500 数据集对比测试Text、RCFile、Parquet 以及 ORCFile 占用的磁盘空间,如下图所示。结果表明,想比如其他存储格式,ORCFile 能达到更高的压缩比。尽管ORC已经独立称为一个Apache项目,但由于它提供的编程 API 对复杂数据集(比如多层潜逃数据)不够友好,目前定义和创建ORC文件主要通过HQL(Hive Query Language)完成的。

    (2)支持 ACID

        Hive 在 ORC File 基础上,基于“base file + delta file”的模型实现了对 ACID 的支持。即数据首先被写入一个base file中,之后的修改数据被写入一个delta file,Hive将定期合并这两个文件。但需要注意的是,Hive ORC ACID并不是为OLTP场景设计的,它能较好地之际一个事物中更新上百万(甚至更多)条记录,但难以应对一小时内上百万个事物的场景。

    (3)内置索引

    ORC提供了 file、stripe 以及 row 级别的索引,方便用户查找定位目标数据:

    1> file 级别索引:文件级别的统计信息(如最大值,最小值等)。

    2> stripe 级别索引:ORC文件将数据划分成若干个固定大小的stripe,每个stripe可定义记录内部数据统计信息。

    3> row 级别索引:每个stripe 内部每10000行会生成数据索引信息和统计信息。

    ORC 是按列存储数据的,支持投影操作,结合各级别索引,ORC可轻易过滤掉查询无关的数据行和数据列。ORC 也允许用户根据自己的需要,在各级别索引中添加自定义信息。

    3.2 Parquet 文件

        Parquet 是由 Twitter 实现并开源的,解决 Twitter 内部日益增长的数据存储和处理问题。据有关资料介绍,当时 Twitter 的日增数据量达到压缩之后 100TB+,存储在HDFS上,采用各种计算框架(MapReduce、Spark等)和分析工具(Hive等)进行处理,其中最主要的是日志数据。日志数据结构是复杂的嵌套数据类型,例如一个典型的日志的schema有87列,嵌套了七层。所以需要设计一种列式存储格式能支持复杂的嵌套类型数据,也能够适配主流数据处理框架,而Parquet正是在这种背景下实现的。

        Parquet灵感源于 Google Dremel 的列式存储格式,它使用“record shredding and assembly algorithm”来分解和组装复杂的嵌套数据类型同时辅以按列的高效压缩和编码技术,从而达到降低存储空间,提高IO效率的目的。

        Parquet 文件存储格式的设计与ORC较为类似,是一种自描述的列式存储格式,如下图所示,它先按照行切分数据,形成一个Row Group,在每个Row Group内部,以列为单位存储数据。

    1> Row Group:一组行数据,内部以列为单位存储这些行。当向Parquet文件写入数据时,Row Group 中的数据会缓冲到内存中直到达到预定大小,之后才会刷新到磁盘上;当从Parquet文件读取数据时,每个 Row Group 可作为一个独立数据单元由一个任务处理,通常大小在 10MB 到 1GB 之间。

    2> Column Chunk:每个Column Chunk 由若干个Page构成,读取数据时,可选择性跳过不感兴趣的Page。

    3> Data Page:数据压缩的基本单元,数据读取的最小单元,通常一个Page 大小在 8KB 到 100KB 之间。

    相比于 ORC File,Parquet能更好地适配各种查询引擎(比如Hive、Impala等),计算框架(比如MapReduce、Spark等)和序列化框架(比如Thrift、Protobuf、Avro等),如下图所示,为了实现该目标,Parquet项目被分成三部分。

    1> 存储格式:定义Parquet内部存储格式、数据类型等,这一部分的主要目的是提供一种通用的,与语言无关的列式存储格式。该部分由项目parquet-format实现。

    2> 对象模型转换器:将外部对象模型映射成Parquet内部类型,该部分由parquet-mr实现,目前已经支持Hive、Pig、MapReduce、Cascading、Crunch、Impala、Thrift、Protobug、Arvo等。

    3> 对象模型:内存中数据表现形式,序列化框架,包括Thrift、Protobuf、Avro等,均属于对象模型。

    3.3 CarbonData 文件

        CarbonData 是华为开源的一种新的高性能数据存储格式,针对当前大数据领域分析场景需求各异而导致的存储冗余问题,CarbonData 提供了一种新的融合数据存储方案,以一份数据同时支持“任意维度组合的过滤查询、快速扫描、详单查询等”多种应用场景,并通过多级索引、字典编码、列存储等特性提升了IO扫描和计算性能,实现百亿级数据秒级响应。相比Parquet 和 ORC,CarbonData 的优势在于以下几点:

    (1)独特的数据组织方式:更加灵活的行列式存储格式,对于经常一起出现的列,可以将其设置为列组,设置为列组的列会按行的方式进行存储,然后与其他列或列组一起按列存储。

    (2)多层次索引:CarbonData 实现了文件和数据块级别的索引,同时引入多维主键和倒排索引实现行级别和列级别的索引。

    (3)全局字典编码:CarbonData 实现了字符串的全局字典编码,这样仅需要在磁盘上保存较小的整数而无需保存原始字符串,这大大增加了数据处理速度,并减少了存储空间。

    (4)支持数据的更新与删除:CarbonData 支持批量和离线数据更新和加载,以更好地支持OLAP场景。

        CarbonData 文件中每一个存储单元称为一个 Blocklet,对应于 Parquet 的一个 Row Group。每个 Blocklet 内按列分为多个 Column Chunk,用以存储某列数据,而每个 Column Chunk 由连续的多个 Page 组成,每个 Page 中包含 32000行数据。

    3.4 ORC、Parquet 和 CarbonData 对比

        一般而言,ORC 通常作为数据表的数据格式应用在 Hive 和 Presto 等计算引擎中,它们对 ORC 读写进行了优化;而 Parquet 提供了非常易用的读写API,用户可在应用程序(比如 Spark 或 MapReduce 等分布式程序)中直接读写 Parquet 格式的文件;而 CarbonData 在索引和数据更新等方面有良好的支持,可用在多维 OLAP 分析等场景中。

     

                                                                                           ---内容主要来自于《大数据技术体系详解:原理、架构与实践》

     

     

     

    展开全文
  • FAT32 文件系统在磁盘上的结构 文章目录FAT32 文件系统在磁盘上的结构卷结构数据区域的安排物理地址物理扇区号逻辑扇区号分区区域和常规区域用户区域的安排簇簇的状态分区区域的安排MRB与分区表位置分区表的内容系统...

    FAT32 文件系统在磁盘上的结构


    这个是根据SD协议上Part2部分的文件系统规格文档。

    卷结构

    先看一下卷结构例子:

    高容量SD存储卡的容量结构在本节中指定。为了将数据区域标识为一个分区,主引导记录和分区表存在于卡的第一个扇区以及标准容量SD存储卡中。大容量SD存储卡采用FAT32文件系统。

    在这里插入图片描述

    数据区域的安排

    用于大容量SD存储卡的数据区安排与用于标准容量SD存储卡的安排相同。
    也就是说,这类卡具有物理地址、物理扇区号和逻辑扇区号的概念,数据区也分为分区区和常规区域。

    物理地址

    每个部门应由一个物理地址,包括SD卡本身的参数识别。

    物理扇区号

    卷上的每个扇区应由物理扇区编号标识。物理地址和物理扇号之间应该有一对一的对应关系。物理扇区编号应按升序分配,从0开始。

    逻辑扇区号

    分区上的每个扇区都应该通过一个逻辑扇区号来标识。分区的第一个扇区应该被分配为0作为逻辑扇区号。物理扇区编号之间应该有一一对应关系。

    分区区域和常规区域

    数据区空间应分为分区区域常规区域两部分。常规区域分为系统区域用户区域
    分区区域应该占用物理扇区编号为0NOM-1的扇区,其中NOM是主引导记录和分区表中的扇区数。
    常规区域是卷的一个分区,分为系统区域用户区域
    系统区域应占用物理扇区编号NOMNOM+SSA-1的扇区,其中SSA为系统区域内扇区的数量。系统区域应包含指定常规区域的记录格式的描述符。系统区域内不得包含任何文件的任何部分。
    用户区域应使用物理扇区编号以NOM+SSA开头的扇区。用户区域应包含文件和目录,并记录用户数据。

    我这里有一个16G的U盘,在Windows上格式化,参数如下:

    在这里插入图片描述

    使用Winhex工具打开,当前如下所示:

    在这里插入图片描述

    打开Volume卷后,可以看到,卷结构与协议上面描述的是有差异的,看样子应该是Winhex展示的引导扇区数分区引导信息,而不是主引导记录(后续分析):

    在这里插入图片描述

    用户区域的安排

    大容量SD存储卡的用户区布置与标准容量SD存储卡的布置相同。
    即将用户区域组织为簇(集群)单元,簇有三种状态。

    用户区域应该被组织成称为簇的分配单元。每一组应由相同数目的部门组成。每个簇应该通过一个唯一的簇(集群)号来识别。簇编号应该被分配以2开始的整数。

    簇的状态

    应将一种状态分配给每一组,并应是下列状态之一:

    • 分配给文件:簇已经被分配
    • 可供分配:簇可以被分配
    • 有缺陷的:这个簇有缺陷,不可以被分配

    每个簇的状态应根据ISO/IEC 9293进行标识。

    分区区域的安排

    数据区域的第一个扇区有一个主引导记录,其中包括可执行代码和分区表,其中包括识别分区的信息以及标准容量SD存储卡。

    MRB与分区表位置

    在这里插入图片描述

    (BP 0 to 445) Master Boot Record 主引导记录

    这个缩写就是MRB,此字段的内容不由本规范指定。

    (BP 446 to 461) Partition Table (partition1) 分区表1

    此字段应指定卷中第一个分区的信息。此分区是指用户无需相互身份验证即可访问的常规区域。按表4-2记录。

    (BP 462 to 477) Partition Table (partition2) 分区表2

    这个字段应该被记录为零,因为一个卷应该由单个规则区域组成。

    (BP 478 to 493) Partition Table (partition3) 分区表3

    这个字段应该被记录为零,因为一个卷应该由单个规则区域组成。

    (BP 494 to 509) Partition Table (partition4) 分区表4

    这个字段应该被记录为零,因为一个卷应该由单个规则区域组成。

    (BP 510 and 511) Signature Word 签名字段

    该字段应记录为55h (BP 510)AAh (BP 511)

    分区表的内容

    分区表如下所示:

    在这里插入图片描述

    (BP 0) Boot Indicator 启动指示器

    如果使用SD存储卡引导,则该字段记录为80h。否则,此字段记录为00h。现在应该比较少用SD卡作为启动盘,我们格式化的卡这个字段一般都是00h

    (BP 1) Starting Head 分区起始头

    这个字段应该指定分区的起始头。如果分区的起始位置超过8032.5MB(8,422,686,720字节),则该字段应记录为FEh。

    (BP 2 and 3) Starting Sector / Starting Cylinder 分区的起始扇区和柱面

    此字段应指定分区的起始扇区和柱面。在这个字段应使用中的6位(BP 2中的0到5位)用于开始扇区。该字段应使用中的10位(BP 2中的6位和7位,BP 3中的0位到7位)用于启动柱面。如果分区的起始位置超过8032.5MB(8,422,686,720字节),则该字段将被记录为FFFFh

    (BP 4) System ID 系统ID

    如果分区的结束位置小于8032.5MB(8,422,686,720字节),则该字段应记录为0Bh。否则,此字段记录为0Ch

    (BP 5) Ending Head 分区的结束头

    这个字段应该指定分区的结束头。如果分区的结束位置超过8032.5MB(8,422,686,720字节),则该字段应记录为FEh

    (BP 6 and 7) Ending Sector / Ending Cylinder 分区的结束扇区和柱面

    此字段应指定分区的结束扇区和柱面。6位(BP 6中的0位到5位)在该字段应使用中用于结束扇区。在这个字段应使用中有10位(BP 6中的6位和7位,BP 7中的0位到7位)用于结束柱面。如果分区的结束位置超过8032.5MB(8,422,686,720字节),则该字段将被记录为FFFFh

    (BP 8 to 11) Relative Sector 相对扇区

    此字段应指定在此分区的开始扇区之前存在的扇区数量。分区的起始扇区应该与附录C.2中指定的边界单元对齐。对排列的详细解释在附录C.2中描述。

    (BP 12 to 15) Total Sector 总扇区数

    此字段应指定分区上的扇区数。

    由于在Windows上格式的没有看到分区表,这里暂时略过。

    系统区域的安排

    系统区域

    系统区域应该包含分区引导扇区、FS信息扇区和文件分配表(FAT)。这些扇区应在卡上记录两次,以便备份。FAT32没有为根目录保留区域。它应该像其他目录一样位于用户数据区域。

    分区引导扇区和FS信息扇区

    系统区域的第一个扇区应该包含分区引导扇区。它应该包含分区的参数,如簇大小、分区大小等。
    系统区域的第二个扇区应该包含FS信息扇区。它应该包含额外的信息,如空闲簇(集群)数,下一个空闲簇(集群),等等。
    系统区域的第三个扇区应该为引导扇区保留。这个扇区有签名字。即55h记录在BP 510中,AAh记录在BP 511中。在第三扇区的其他字节将被保留为系统使用,他们不应在本规范中指定。
    这个区域的大小应该记录在分区引导扇区的保留扇区计数字段中。在这个规范中,大小应该用于用户数据区域的对齐。更多细节见附录C.2。

    以上3个区域都要在卡片上记录两次。在逻辑扇区号(LSN) 0 ~ 2和6 ~ 8中记录如下。

    在这里插入图片描述

    文件分配表(FAT表)

    FAT应该包含一个格式标识符和一些条目,每个条目表示用户区域的簇。这些条目应从2开始连续编号,条目编号应等于相应簇的簇编号。
    FAT表中的每一项都应表明相应簇的状态。FAT条目应使用用于标识分配给每个文件的一组簇。

    文件结构

    分区启动扇区

    在分区的头部有一个分区引导扇区。对于FAT32文件系统,有些字段是从ISO/IEC 9293的扩展FDC描述符扩展而来的。分区引导扇区应该像前面描述的那样记录两次。

    在这里插入图片描述

    在磁盘上的表现是这样的:
    在这里插入图片描述

    (BP 0 to 2) Jump Command

    该字段将指定引导程序的跳转命令。应记录为EBh (BP 0)、XXh (BP 1)和90h (BP 2),或E9h (BP 0)、XXh (BP 1)和XXh (BP 2)。XXh表示该值在本规范中未作规定。

    (BP 3 to 10) Creating System Identifier

    该字段应为系统指定标识。

    (BP 11 and 12) Sector Size

    此字段应指定扇区的大小(以字节为单位)。应记录为512号。

    (BP 13) Sectors per Cluster

    这个字段应该指定每个簇(集群)的扇区数。应记录如下编号:1、2、4、8、16、32或64。确定个簇(集群)大小时应考虑物理层的擦除块大小。该字段应按照本规范的建议进行记录。该建议的详细解释载于附录C.2.3。

    (BP 14 and 15) Reserved Sector Count

    这个字段应该指定保留给系统使用的扇区的数量。此字段应用于用户数据区域的对齐。对排列的详细解释在附录C.2中描述。

    (BP 16) Number of FATs

    这一栏应注明FAT表的数量。应记录为数字2。

    (BP 17 and 18) Number of Root-directory Entries

    这个字段应该指定FAT12 / FAT16文件系统根目录中的条目数。FAT32文件系统不应该使用这个字段,应该记录为数字0。

    (BP 19 and 20) Total Sectors

    这个字段应该指定大小为65535扇区或更小的分区上的扇区数量。FAT32文件系统不应该使用这个字段,应该记录为数字0。

    (BP 21) Medium Identifier

    在本规范中,此字段应记录为F8h。

    (BP 22 and 23) Sectors per FAT

    这个字段应该指定FAT12 / FAT16文件系统的每个FAT表应该占用的扇区数量。FAT32文件系统不应该使用这个字段,应该记录为数字0。

    (BP 24 and 25) Sectors per Track

    此字段应指定每个磁道中的扇区数。此参数取决于SD存储卡的参数。该字段应按照本规范的建议进行记录。该建议的详细解释见附录C.2.2。

    (BP 26 and 27) Number of Sides

    此字段应指定可记录的边数。此参数取决于SD存储卡的参数。该字段应按照本规范的建议进行记录。该建议的详细解释见附录C.2.2。

    (BP 28 to 31) Number of Hidden Sectors

    此字段应指定在此分区的开始扇区之前存在的扇区数量。分区的起始扇区应该与附录C.2中指定的边界单元对齐。对排列的详细解释在附录C.2中描述。

    (BP 32 to 35) Total Sectors

    如果BP 19 and 20中的字段被记录为零,则该字段将指定分区上的扇区数。FAT32文件系统不能使用BP 19 and 20。因此,该字段不能是零。

    (BP 36 to 39) Sectors per FAT for FAT32

    他的字段应该指定FAT32文件系统中每个FAT表应该占用的扇区数。

    (BP 40 and 41) Extension Flag

    此字段将指定FAT镜像的状态。

    Bits 0 to 3: 这些位应指定以零为基础的活动FAT表的数量。只有在禁用镜像时,这些位才是有效的。

    Bits 4 to 6: 保留。

    Bits 7: 表示FAT表在运行时镜像到所有FAT中。1表示只有一个FAT表是活跃的;它是在0到3位中引用的那个。

    Bits 8 to 15 : 保留。

    (BP 42 and 43) FS Version

    这个字段应该指定FAT32文件系统的版本号。高字节是主修订号。低字节是小修订号。这个字段应该记录为0000h,显示版本0:0。

    (BP 44 to 47) Root Cluster

    这个字段应该指定根目录的第一个簇(集群)的簇(集群)号。这个值应该是2,或者之后第一个可用的(没有缺陷的)簇(集群)可用。

    (BP 48 and 49) FS Info

    这个字段应该指定FS Info扇区结构被记录的区域的扇区编号。在这里,扇区编号表示与系统区域的首扇区的偏移量。也就是说,扇区编号0表示系统区域的首扇区的位置。
    此字段应记录为第1扇区。显示FS Info扇区应该位于系统区域的第二个扇区。

    (BP 50 and 51) Backup Boot Sector

    这个字段应该指定引导扇区副本所在区域的起始扇区编号。在这里,扇区编号表示与系统区域的首扇区的偏移量。也就是说,扇区编号0表示系统区域的首扇区的位置。
    此字段应记录为第6扇区。它显示引导扇区的副本应该记录在系统区域的第7扇区开始的区域中。

    (BP 52 to 63) Reserved

    该领域应保留以备将来标准化之用。它应记录为零。但是,由于在其他设备上可能会设置一个非00h的值,所以在运行时不应期望设置00h。

    (BP 64) Physical Disk Number

    此字段将指定BIOS物理磁盘号。此字段应记录为80h。

    (BP 65) Reserved

    该领域应保留以备将来标准化之用。它应记录为零。但是,由于在其他设备上可能会设置一个非00h的值,所以在运行时不应期望设置00h。

    (BP 66) Extended Boot Record Signature

    此字段应使用用于标识该结构。此字段记录为29h。

    (BP 67 to 70) Volume ID Number

    此字段应指定卷识别号。

    (BP 71 to 81) Volume Label

    此字段应指定卷标签。

    (BP 82 to 89) File System Type

    此字段将指定文件系统的类型。该字段应记录为FAT32...,最后三个字节是20H,我这里用.代替了。

    (BP 90 to 509) Field reserved for system use

    此字段应保留供系统使用。在本规范中不作规定。

    (BP 510 and 511) Signature Word

    该字段应记录为55h (BP 510)和AAh (BP 511)。

    FS Info 扇区

    在分区引导扇区的下一个扇区中有一个FS Info扇区。这个结构在FAT12 / FAT16卷中不存在。FS Info扇区应按前面所述记录两次。

    在这里插入图片描述

    在磁盘上的表现是这样的:

    在这里插入图片描述

    (BP 0 to 3) Lead Signature

    此字段应使用用于验证FS信息扇区的开头。记录为52h (BP 0)、52h (BP 1)、61h (BP 2)、41h (BP 3)。

    (BP 4 to 483) Reserved

    该领域应保留以备将来标准化之用。它应记录为零。但是,由于在其他设备上可能会设置一个非00h的值,所以在运行时不应期望设置00h。

    (BP 484 to 487) Structure Signature

    此字段应使用作为验证FS Info扇区完整性的附加签名。记录为72h (BP 484)、72h (BP 485)、41h (BP 486)、61h (BP 487)。

    (BP 488 to 491) Free Cluster Count

    这个字段应该包含卷上最后已知的空闲簇(集群)计数。值FFFFFFFFh表示空闲计数是未知的。这个字段的内容应该在卷挂载时进行验证(然后由文件系统驱动程序实现在内存中维护)。建议此字段包含卷卸载时(在有控制的卸载/关闭期间)空闲簇(集群)的准确数量。

    (BP 492 to 495) Next Free Cluster

    这个字段应该包含卷上第一个可用(空闲)簇(集群)的簇(集群)号。值FFFFFFFFh表示不存在关于第一个可用(空闲)簇(集群)的信息。此字段的内容应在卷挂载时进行验证。建议在卷卸除时(在有控制的卸除/关闭期间)适当更新此字段。

    (BP 496 to 507) Reserved

    该领域应保留以备将来标准化之用。它应记录为零。但是,由于在其他设备上可能会设置一个非00h的值,所以在运行时不应期望设置00h。

    (BP 508 to 511) Trail Signature

    此字段应使用用于验证FS Info扇区中数据的完整性。记录为00h (BP 508)、00h (BP 509)、55h (BP 510)和AAh (BP 511)。

    文件分配表FAT: File Allocation Table

    文件分配表由32位FAT条目组成。下表描述了每个FAT条目值。FAT32 FAT条目的高4位被保留。在修改任何FAT32 FAT条目时,所有FAT实现都要保留高4位的当前值,除非在卷初始化(格式化)时,整个FAT表需要设置为0。FAT32卷不应该被配置包含用于分配>= FFFFFF7H的簇(集群)号。

    在这里插入图片描述

    FAT中的前两个条目(8字节)被保留。这些8个字节的FAT应记录为F8h (BP 0), FFh (BP 1), FFh(BP 2), 0Fh(BP 3), FFh(BP 4), FFh (BP 5), FFh (BP 6)和0Fh (BP 7)。但是,文件系统驱动程序可以将BP 7的特定两位用于脏卷标志,如下所示。

    Bit 3 (Clean Shutdown Bit) :

    如果bit为1,则卷为“干净”。 可以安装该卷以进行访问。
    如果bit为0,则卷为“脏”,表明FAT文件系统驱动程序无法正确卸装该卷(在先前的安装操作过程中)。 卷内容
    应该扫描文件系统元数据是否有损坏。

    Bit 2 (Hard Error Bit) :

    如果该位为1,则没有遇到磁盘读/写错误。
    如果bit为0,则文件系统驱动程序实现在磁盘上遇到磁盘I / O错误。
    上次安装它的卷,这表明某些扇区可能已损坏。 卷内容应使用磁盘修复实用程序进行扫描,该实用程序对其进行表面分析以查找新的坏扇区。

    FAT的扇区可能包括未使用的区域,因为簇(集群)的数量将决定FAT的字节大小。未使用的区域应记录为零。

    在磁盘上的表现是这样的:我这边新增了一个54KB大小的文件(格式化的时候一个簇64K,这个文件一个簇内可以放下)后新增的一个簇就是这个,簇的值表示当前簇就是结束簇(即一个簇)。
    在这里插入图片描述
    当我这边再新增了一个170KB大小的文件(格式化的时候一个簇64K,这个文件三个簇内可以放下),其内容表现如下,(最后一个簇9指示当前簇是最后一个簇,至于怎么找文件簇开始的地方,要看后面的目录项内容):

    在这里插入图片描述

    文件目录

    特征

    目录是一个描述符,它应包含一组目录条目,每个目录条目标识一个文件,一个卷标,另一个目录或未使用。 包含根目录的目录中目录条目的最大数量为65536。
    目录条目的文件名格式必须支持8.3格式。 并且主机也可以支持长文件名(LFN)作为可选。 如果主机不支持“长文件名”,则它可能会忽略“长文件名”条目,而仅引用LFN存储的8.3格式的文件名。

    注意:长文件名功能在附录C.3中描述。

    如上一节所述,在FAT12和FAT16卷上,根目录应紧随最后一个文件分配表。 并且该大小是固定大小,以扇区为单位,该大小是根据分区引导扇区中存储的“根目录条目数”值计算得出的。
    在格式化为FAT32的卷上,根目录可以具有可变大小。 FAT32卷上根目录的第一个群集的位置存储在分区引导扇区的“根群集”字段中。 只有根目录可以包含卷标签条目。 根目录没有名称(在大多数操作系统实现中,使用隐式名称“ \”)。 此外,根目录没有任何关联的日期/时间戳。 最后,根目录不包含点和点条目。

    目录项字段

    下表指示目录条目字段的结构。

    在这里插入图片描述

    在磁盘上的表现是这样的:

    在这里插入图片描述

    (BP 0 to 10) Name and Name Extension

    该字段应包含由包含该字段的相应条目描述的文件或子目录的11个字符(“短”)名称。 该字段在逻辑上由两个部分组成:

    • 8个字符的名字的主要部分
    • 3个字符的扩展名

    如果需要,上述两个组件中的每一个都是“填充尾随空间”(使用值:20h)。

    请注意以下几点:

    1. 隐含的.字符将名称的主要部分与扩展名分开。 .分隔符永远不会存储在此字段中。
    2. 如果此字段的第一个字节为E5h,则表明目录条目是空闲的(可用)。但是,对于日本使用的字符集,E5h是有效的KANJI前导字节值。对于基于KANJI字符集的名称,值05h存储在此字节中(如果需要)以表示E5h。如果FAT文件系统实现将该字节读取为05h,并且使用的字符集为KANJI,则应在将名称返回给应用程序之前在内存中执行适当的替换。
    3. 如果此字段中的第一个字节为00h,则还指示目录条目是空闲的(可用)。但是,在该字段的第一个字节中设置的00h可以指示当前空闲条目之后的所有目录条目也是空闲的。
    4. 此字段中的第一个字节不能等于20h(换句话说,名称不能以空格字符开头)。
    5. 目录中的所有名称均应唯一。

    对包含名称的字符的限制

    • 不允许使用小写字符
    • 名称中字符的非法值如下:
      • 小于20h的值(特殊情况除外,如前所述,此字段的第一个字节为05h)
      • 22h,2Ah,2Bh,2Ch,2Eh,2Fh,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,5Bh,5Ch,5Dh和7Ch

    (BP 11) Attributes

    该字段应指定条目的属性。

    在这里插入图片描述

    属性字节的高两位保留,并且在创建文件时应始终设置为0,并且从不对其进行修改或查看。

    创建新目录时,文件系统实现应确保以下内容:

    • ATTR_DIRECTORY位应在其属性字段中设置
    • 文件长度字段应设置为0
    • 至少应分配一个群集–“起始群集号低”字段和“起始群集号高”字段的内容应指第一个分配的群集号
    • 如果仅分配了一个簇(集群),则相应的文件分配表条目应指示文件结束条件
    • 分配的簇(集群)的内容应初始化为0
    • 除根目录外,每个目录在目录开头应包含以下两个条目:
      • 第一个目录条目的目录名称应设置为.:该点条目引用当前目录。 应遵循上面针对“属性”字段和“文件长度”字段列出的规则。 由于点条目是指当前目录(包含点条目的目录),因此“起始簇号低”字段和“起始簇号高”字段的内容应与当前目录的内容相同。 所有日期和时间字段应设置为与包含目录的值相同的值。
      • 第二个目录条目的目录名称应设置为..:此点条目是指当前目录的父目录。 应遵循上面针对“属性”字段和“文件长度”字段列出的规则。 由于点号条目是指当前目录的父目录(包含点号条目的目录),因此“起始群集号低”字段和“起始群集号高”字段的内容应与当前目录的父目录相同。 如果当前目录的父目录是根目录,则“起始群集号低”字段和“起始群集号高”字段的内容应设置为0。所有日期和时间字段应设置为与包含目录的值相同的值。

    (BP 12) Reserved for NT

    该字段应保留。 该字段应设置为0。

    (BP 13) Created Time Tenth

    该字段应指定文件创建时间的组成部分。 该字段实际上包含十分之一秒的计数。 有效值范围是0-199(含)。 如果不支持此字段,则应在创建文件时将其设置为0,而在其他文件操作中将其忽略。

    (BP 14 and 15) Created Time

    该字段应指定文件创建时间。 详细格式将在以下部分中介绍。 如果不支持此字段,则应在创建文件时将其设置为0,而在其他文件操作中将其忽略。

    (BP 16 and 17) Created Date

    该字段应指定文件创建日期。 详细格式将在以下部分中介绍。 如果不支持此字段,则应在创建文件时将其设置为0,而在其他文件操作中将其忽略。

    (BP 18 and 19) Last Access Date

    该字段应指定最后访问日期。 上次访问定义为对该条目描述的文件/目录执行的读取或写入操作。 该字段应在文件修改(写操作)时更新,并且日期值应等于“记录日期”字段。 详细格式将在以下部分中介绍。 如果不支持此字段,则应在创建文件时将其设置为0,而在其他文件操作中将其忽略。

    (BP 20 and 21) Starting Cluster Number High

    该字段应为该条目描述的文件/目录指定第一个数据簇号的高位字。

    (BP 22 and 23) Time Recorded

    该字段应指定最后的修改(写入)时间。 创建文件时,此字段应等于“创建时间”字段。 详细格式将在以下部分中介绍。 所有主机均应支持该字段。

    (BP 24 and 25) Date Recorded

    该字段应指定最后修改(写入)日期。 创建文件时,此字段应等于“创建日期”字段。 详细格式将在以下部分中介绍。 所有主机均应支持该字段。

    (BP 26 and 27) Starting Cluster Number Low

    该字段应指定该条目描述的文件/目录的第一个数据簇号的低位字。

    (BP 28 to 31) File Length

    该字段应指定32位数量,该数量包含此条目描述的文件/目录的字节大小。

    日期和时间格式

    目录条目中的日期和时间格式如下。

    (Date Format)

    目录条目中与日期相关的字段的内容应采用以下格式:

    • Bits 0~4 : 代表每月的某天(有效范围:1… 31(含))
    • Bits 5~8 : 代表一年中的月份(1 =一月,12 =十二月,有效范围:1…12(含)
    • Bits 9~15 : 1980年以来的年数(有效范围:0…127(含)允许代表1980年到2107年)

    (Time Format)

    目录条目时间戳是16位值,粒度为2秒。 目录条目中与时间相关的字段的内容应采用以下格式:

    • Bits 0~4 : 经过的秒数-以2秒为增量(有效范围:0…29(含0…29),允许表示0到58秒)
    • Bits 5~10 : 代表分钟数(有效范围:0…59(含))
    • Bits 11~15 : 代表小时(有效范围:0…23(含))

    有效时间范围是从午夜00:00:00到23:59:58。

    与FAT12 / FAT16文件目录的区别

    FAT32文件系统的文件目录与FAT12 / FAT16文件系统(ISO / IEC 9293)相似,但是存在一些差异。 它们之间的主要区别如下:

    • 对于FAT32,根目录并不位于特殊位置,它的大小可以可变,并且是一个群集链,就像其他目录一样。
    • 添加了目录条目中的以下字段:为NT保留,创建时间十分之一,创建时间,创建日期,最后访问日期和起始簇号高

    用户数据区域

    用户区应由一些簇(集群)组成。 每个群集分别具有一个群集编号。 用户区域中的第一个群集对应于群集编号2。
    尽管可以按扇区进行读/写,但是建议使用最小尺寸与物理层上建议的读/写相同的最小单位进行读/写。 除此之外,SD存储卡文件系统没有特别限制。

    LFN长文件名实现

    SD存储卡文件系统中的LFN

    对于SD记忆卡的所有FAT12 / FAT16 / FAT32文件系统,文件名格式必须支持8.3格式。 此外,主机还可以支持长文件名(LFN)作为可选。 本节介绍“长文件名”格式和用法。

    注意:本节中描述的长文件名是可选的。 本节中描述的长文件名规范包括Microsoft FAT规范的某些部分,其版权归Microsoft所有,但已获得SD卡协会的许可。

    FAT长目录条目

    目录条目中的“名称和名称扩展名”字段仅允许包含11个字符的文件/子目录名称,该文件名由主体部分(最大长度为8个字符)和扩展名(最大长度为3个字符)组成。该字段的内容也称为“短名称”,相应的目录条目也称为短名称目录条目。应用程序和用户通常更喜欢为文件/子目录创建更长的名称(更具描述性)。本节介绍如何在媒体上存储如此长的文件名。
    目标文件或子目录的长文件名存储在一组(一个或多个)附加目录条目中,这些附加目录条目与描述目标文件或子目录的简称目录条目相关联。这组附加目录条目(也称为长名称目录条目)应紧接在相应的短名称目录条目之前,因此在物理上与短名称目录条目相邻。

    注意:长名称目录条目的顺序以相反的顺序存储(该集中的最后一个条目先存储,然后是条目n-1,然后是条目n-2,依此类推,直到条目1)。

    下表描述了长名称目录条目结构:

    在这里插入图片描述

    下面说明了名称目录条目的存储时间:

    在这里插入图片描述

    在磁盘上的表现是这样的:在这里插入图片描述

    序数生成

    在一组这样的条目(与短名称目录条目相关联)中存储每个长名称目录条目的序号时,应遵循以下规则:

    • 集合的第一个成员的LDIR_Ord值为1。
    • 每个后续条目的LDIR_Ord值应包含一个单调递增的值。
    • 集合的第N个(最后一个)成员应包含值(N | LAST_LONG_ENTRY)

    如果长名称目录条目集的任何成员不遵循上述规则,则该集被视为已损坏。

    校验和生成

    在创建短名称目录条目和长名称目录条目时,将对包含在短名称目录条目中的名称计算一个8位校验和。 短名称条目中名称的所有11个字符都将用于校验和计算。 校验和放置在LDIR_Chksum字段中的每个长名称目录条目中。 如果与适当的短名称目录条目相关联的长名称条目集合中的任何校验和与短名称目录条目中包含的名称的计算出的校验和不一致,则认为长名称目录条目集合已损坏 。

    以下算法描述了用于生成校验和值的逻辑:

    在这里插入图片描述

    示例说明长名称的持久性

    提供以下示例,以说明如何在多个长名称目录条目中存储长名称。 名称也以NULL终止,并用FFFFh字符填充,以检测长名称字段的损坏。 完全适合一组长名称目录条目的名称(即13的整数倍)不是NULL终止的,也不用FFFFh填充。

    名称:“ The quick brown.fox”

    在这里插入图片描述

    长文件名的名称限制和字符集

    长文件名限制为255个字符,不包括结尾的NULL。 这些字符可以是为短文件名定义的字符的任何组合,并加上在长名中多次使用的句点(“。”)字符。 空格也是长文件名中的有效字符,因为它始终是短文件名。 长文件名允许以下六个特殊字符(短文件名不合法):+ , ; = [ ]

    允许在长文件名中包含嵌入式空格。 长文件名中的前导和尾随空格将被忽略。

    名称中允许前导和嵌入句点,并存储在长文件名中。 尾随时间段将被忽略。

    长文件名存储在UNICODE的长目录条目中。 UNICODE字符是16位字符。 不能将UNICODE存储在短名称目录条目中,因为其中存储的名称是8位字符或DBCS字符。

    传递给文件系统的长文件名不会转换为大写,并且会保留其原始大小写值。 UNICODE通过始终将小写字符转换为单个唯一的大写字符来解决某些OEM代码页中普遍存在的大小写映射问题。

    规则的名称创建和匹配

    所有长文件名和短文件名的并集定义为卷中包含的对象的名称空间。

    对于这样的名称空间,应遵守以下规则:

    • 特定目录中的任何名称,无论是短名称还是长名称,都只能出现一次(以区别形式出现,如果忽略,则这些名称应视为冲突)。
    • 当媒体上的字符(无论是存储在OEM字符集还是UNICODE中)不能转换为OEM或ANSI代码页中的适当字符时,总是将其转换为“ _”(下划线)字符-该字符为 媒体上未修改。 在所有OEM代码页和ANSI中,“ _”字符均相同。
    展开全文
  • 本文来自作者投稿,原作者:zyz1992 ...Innodb的存储格式 我们知道,关于Mysql这种关系型数据库,里面保存的数据最终都是要持久化到磁盘文件上面的。磁盘文件里存放的物理格式就是数据页(关于数.

    本文来自作者投稿,原作者:zyz1992

    关于MySql数据库,相信很多人都不陌生,这是当今最常用的一种关系型数据库,关于MySql的知识也是很丰富的。

    那么,不知道大家有没有想过这样的问题:MySql中的数据是存在哪的?又是如何存储的呢?

    本文就来深入分析一下这些问题。文章内容很长,建议收藏,建议大家静下心来仔细阅读,一定会有收获!

    Innodb的存储格式

    我们知道,关于Mysql这种关系型数据库,里面保存的数据最终都是要持久化到磁盘文件上面的。磁盘文件里存放的物理格式就是数据页(关于数据页,如果不太理解先忽略,后续文章单独介绍),数据页中存放的是一行一行的记录,但是对于数据页中的每一行数据他又是怎么存储的呢?

    我们拿Mysql中最常用的Innodb引擎来重点说,介绍下存储格式是怎样的。

    MySQL中存储有3种:

    server层格式:与存储引擎无关,Binlog存储常用的一种 (Bin Log 我们前面已经详细介绍过了,这个是MySql主从复制的一个很重要的文件)

    索引元组格式:InnoDB存取过程记录的中间状态,是InnoDB在内存中存储的格式 (换句话说我们的增删改的操作都是在内存中执行的,这个只是一种临时状态)

    物理存储格式:记录在物理页面中的存储格式,即compact格式,与索引元组格式一一对应。(这个是数据在磁盘存储的真正的格式)

    MySql 的 InnoDB 存储引擎和大多数数据库一样,都是以行的形式存储数据的,我们可以通过SHOW TABLE STATUS查看到行的的存储格式。

    InnoDB 储存引擎支持有四种行储存格式:COMPACT、Redundant、Dynamic 和 COMPRESSED。默认为COMPACT。

    其他的参数我们这里不关注,仅仅看 Row_format 这列,这里我们可以看到行的存储格式是 Compact,Compact 存储数据的格式大致如下这样

    对于我们看到的每一行数据,我们最先看到的好像并不是各个列,而是一些类似列的描述信息。没错,其实在存储的时候都会有一些都字段来描述这一行的信息,这就好比缓存池中的描述缓存页的描述数据类似。

    上面的图片大家可以这么简化来对待,事务ID回滚指针大家先不要关注,免得因为这个产生干扰而难于理解

    1、变长字段 varchar 是如何存储的

    一般情况下,我们要存储的数据是并不能确定他的长度的,大部分情况下都是一些变长的数据,以varchar为例,假设现在三个字段,字段类型分别为:varchar(10),char(1),char(1),char大家都是知道的,存储的基本是一些已知的长度固定的数据,假设这三个类型的字段分别有如下的数据:

    第一行:mysql a a;第二行:dog b c;画个图来帮助大家想象,现在你看到的是数据中为我们展现的样子。

    但是在磁盘中可不是这样子的,前文已经提到过,表空间和行这些其实是逻辑上的概念,而数据页是一种物理概念,也就是说我们看到的样子在磁盘中的样子本本是不一样的。

    在磁盘中这两条记录大致是这样子的:mysql a a dog b c,他们在磁盘中都是挨在一起存储的。

    是不是瞬间感觉想要去查找一条数据非常麻烦,告诉你:是的,所以 MySql在设计的时候才会使用行格式存储,才会有前面的哪些变长字段列表和标志位以及记录信息,这些就是用来记录一行的记录的信息,换句话说,MySql是通过这些描述信息来定位到一行中的具体记录的。

    以第一行记录为例,它在磁盘中的记录情况大致是下面这样子的,首先我们需要明确知道的是各个字段的类型MySql是很清楚的,在这个基础上我们能看明白下面和想通后面的事情。首先我们看到 mysql是5个字符,使用十六进制表示是 0x05,所以他的存储大概是这样子的:

    同理第二行数据类似这样子的:

    相信大家在看到这里已经大概能推测出MySql这个时候是怎么读读取数据的了,就是他会先根据变长字段长度列表中描述的变长字段的信息去查找变长字段,例如第一行,MySql解析到变长字段是5,所以他会在mysql a a dog b c 这些里面取出5个字符,也就是 mysql,紧接着后面是两个 char(1) 也就是两个 a 在依次取出来。

    中间设备。由浅入深,我们慢慢来,刚刚上面说到的仅仅是一种非常简单的情况,这个首先是帮助大家理解,让大家先明白有这么个回事,是这么回事,然后在慢慢的挖掘,我们一定要一个萝卜一个坑的去踏实学习

    现在如果是多个varchar类型的字段怎么办?例如:varchar(3),varchar(10),varchar(4),char(1),他有一条记录是这样子的:aaa,bb,cccc,d,你根据上面的能推测出磁盘中的行记录是怎么样子的吗?

    你是不是这么想的:磁盘中肯定是这样的:0x03,0x02,0x04 null标志位 记录头信息aaa bb cccc d;这么想的同学请鼻子靠墙:);实际上并不是这样子的。

    当有多个变长字段的时候,MySql在 compact 行格式中,把所有变长类型的长度存放在行记录的开头部位形成一个列表(这个列表就是刚刚上面说的变长字段列表),按照列的逆序存放,也就是大致是这样子的:

    这里我必须要给大家解释下变长字段列表会逆序存放,因为每行记录的都有一个next_record指针 指向下一行 记录头信息和 真实数据 之间的位置。因为这个位置刚刚好,向左读取就是行描述相关信息,向右读取就是真实数据。正好对应变长字段长度列表。画个图来帮助大家理解下:

    说到这里我们来稍微小结一下

    MySql中数据在磁盘的存储小结

    数据在磁盘中的存储在物理空间上面是连续的

    数据是被存放在MySql设计出来的数据页上面的,数据页上面存储的才是最终的一行一行的记录

    行的存储格式默认是Compact

    每一行数据都会有相应的行描述部分,描述部分有【变长字段列表】【NULL标志位】【记录头信息】

    每一行都会有next_record指针,指向记录头和变长字段列表的中间某个位置,方便寻址

    变长列表中的varchar列的描述是逆序的(和字段的顺序相反)这样做的目的在上图中描述的很清楚了

    2、NULL字段是如何存储的

    上面说到了情况都是比较正常的情况,也就说上面提到的字段是没有空值的,不管是变长字段还是char字段,都是有值的,那如果某个字段允许为空,且值确实为空,MySql又是怎么处理的呢?是不是直接存储NULL呢。

    假设MySql针对与Null直接存储,他实际上是按照“NULL”这样字符串的形式存储的,这样显然不行啊,因为字符串要占用空间的啊(一个 NULL 字符串要占用四个字符呢),你都没有值,还占这么多空间,所以MySql肯定不是这样存储的。其实MySql在处理NULL值的时候是会将它通二进制来存储的,且也是逆序的

    MySql是如何通过二进制来存储NULL值的?

    上面的 Compact 格式数据中的【NULL标志位(也可以叫NULL列表)】就是用来存储NULL值的。若有某个字段值为 null,将将其 bit 位置为 1 说明值为 NULL,bit为 0 说明该字段值不为空

    是不是听了解释还是稀里糊涂的,别急,我画个图再来详细介绍下,先假设我们有一张 sutdents 表

    CREATETABLE`students`(

    `name`varchar(10)NOTNULL,

    `address`varchar(255)DEFAULTNULL,

    `gender`char(1)DEFAULTNULL,

    `class`varchar(10)DEFAULTNULL,

    `hobbies`varchar(255)DEFAULTNULL,

    PRIMARYKEY(`name`)

    )

    他有这样一行记录

    我们先看变长字段列表部分(记住是逆序存放的):

    roles是长度为5记作:0x05;address 为null,不放在变长列表中、gender 是 char 类型,不放在变长列表中、class为空,不放在变长列表中、hobby_xx长度为8记作:0x08;所以变长列表的记录为:0x08 0x05

    现在到了NULL标志位了:依旧是从右往左记录字段:name 在设计的时候就是 not null,所示是不会出现在NULL标志为中(Null标志为是用来记录字段可为NULL的字段,字段不可以为NULL的不是会被记录到NULL标志位的),address为NULL记作1,gender不为null记作0,class 为null记作1,hobbies不为null记作0;所以按照字段的顺序结果就是:0101,但是NULL标志位是逆序的,所以NULL标志位存放的结果大概是这样子的:0101,高位补0即可

    我们来模拟读取下这条记录:MySql 对于字段的类型一定是已知的(这个是在创建数据表的时候就已经定下来了),所以对于 name 这种 not nul l的字段是不会去存放在null标志位的,下面是详细的读取步骤:

    name字段是主键,不可能在NULL 标志位中的,又因为 name 是varchar 字段,所以就会去变长字段列中查找,找到值为 0x05 接着就会去字段列表中读取5个字符的长度,也就是 roles ,第一个字段读取成功;

    接着是 address 字段,因为类型是 MySql 已知的,又因为字段值为 null 所以就不需要去读取了,第二个字段读取结束;

    接着是gender字段,是char类型的,直接拿到 f 就可以了;

    下一个是class 字段,因为是null 所以根本不会去变长字段中查找;

    最后一个是 hobbies 字段,因为不为null ,又是第二个变长字段,这个时候就会去 变长字段列表中查找,结果定位到是 0x08 那就读取 8 个字符的长度出来,拿出来是hobby_xx;

    说到这里,关于一行记录的中的变长字段列表和 NULL 标志位具体是如何读取字段值的就给大家介绍完了,不知道大家看到以上内容脑子是不是会展现一条条行记录的描述信息。目前我们只需要了解 varchar 和 NULL 存储的基本就足够了,因为这两个表特殊,也是最经常使用的,其他的字段类型本篇暂且不展开讨论了。

    上面的记录头的信息我们还没有讨论过,下面我们再详细介绍下记录头信息是什么。

    记录头信息

    记录头信息由40位的bit位组成,其各个位的划分和含义如下:

    记录头的各个位的作用其实就已经说的很清楚了,一些概念现在还没法讲解,很多东西需要到索引的时候才能展开讲,这里大家需要明确的就是各个标志位的含义。

    我认为对于记录头的了解到这里就足够了,各个标志位的含义明确了到这个程度就行了,至于更多的可能我们根本接触不到。这一小节就当是科普。

    3、数据在磁盘上到底是怎么存储的

    上面画过这样一张图:

    之前说的是数据大致是这样子在磁盘中存储的:0x03 NULL标志位 记录头信息 dog b c,但是实际上后面的列的数据并是不是我们看到的这个样子,磁盘在存储的时候是根据数据库指定的字符集编码存储起来的你以为可能是上面那样子存储的。

    实际上可能是在样子的:0x03 NULL 标志位 记录头信息 1233 323 223,也就是说实际的数据在磁盘上存储根本不是我们人能认识的,后面的 1233 323 223 这几个是我乱写的,没什么含义,主要是想表明是计算在实际存储的时候是以特定的字符编码来存储的。

    另外每一行数据在被存储的时候实际上还会有隐藏的字段,相信大家对这个应该不会陌生的,row_id 大家应该是知道的,哪怕自己没用过可能也是听过的,这个是数据库自己为我们的每一行记录生成的一个唯一的表示,如果我们没有为数据表指定主键字段,也没有指定 Unique key,那么这个时候数据库内部会帮我们维护一个自增长的 ROW_ID 字段作为主键。

    还有一个隐藏字段就是 事务ID 上面的第二张图上层画出来过,这个顾名思义了,就是和事务相关的一个字段属性字段名为DB_TRX_ID,这个再详解到事务的时候再详细介绍;最后一个也是在上面的第二张图上画出来了,就是回滚指针 DB_ROLL_PTR,回滚也是事务使用到的概念,也是放在事务那边跟大家介绍

    现在再来整体回顾下一行记录在磁盘中的存储的结构大概是什么样子的:

    0x08 0x05 00000101 000001010000000000000000000000000000001021134 44 232343

    说到了存储,我们顺便聊聊和存储相关的一个概念,行溢出。

    行溢出

    说到这里,不知道大家有没有想过一个问题,就是我们一直在说 MySql 存储是以数据页的形式来存储的,然后数据页中记录的是一行行的记录,但是往往常规情况下不会有什么问题。

    但是如果现在有一行记录非常大,因为数据页大小默认也就是16KB,假设某张表里面有text字段也有BLOB字段,且这一行的记录的大小远远超过了一个数据页的大小16KB,这种情况称之为行溢出。

    MySql 是怎么来处理这种行溢出的情况的呢?实际上很简单,一个数据页不够就使用多个数据页,数据页和数据页之间使用链表连起来,之所以能够使用链表连接因为数据页里面是包含了存放指针的 bit 位。对于行溢出的概念了解到这个程度就足够了。我们学习是有的放矢,不是什么都要去刨根问底的。

    结束语

    本片文章详细的介绍了 MySql 存储数据的格式和数据具体在磁盘中是怎么存储的,被存储的数据又是怎么查找的,说白了很多事情都是已经是既定的规则,所谓既定的规则就是很对东西已经被更早的设计出来。

    所以你在使用和了解的使用只需要按照被人的规则来执行,然后在此基础上深入了解下别人为什么这么设计?这样会更有助于我们掌握和理解某个知识点。

    展开全文
  • oracle数据库中是blob或bfile类型2、 图片存储在磁盘上,数据库字段中保存是图片路径。一、图片以二进制形式直接存储在数据库中第一种存储实现(php语言):大体思路:1、将读取到图片用ph...

    商品图片,用户上传的头像,其他方面的图片。目前业界存储图片有两种做法:

    1、  把图片直接以二进制形式存储在数据库中

    一般数据库提供一个二进制字段来存储二进制数据。比如mysql中有个blob字段。oracle数据库中是blob或bfile类型

    2、  图片存储在磁盘上,数据库字段中保存的是图片的路径。

    一、图片以二进制形式直接存储在数据库中

    第一种存储实现(php语言):

    大体思路:

    1、将读取到的图片用php程序转化成二进制形式。再结合insert into 语句插入数据表中的blob类型字段中去。

    3、  从数据库取出图片展示的时候。则是直接发送图片内容

    4、

    $row=mysql_fetch_object($result); Header( "Content-type: image/gif"); echo $row->this_image;

    实现代码如下:

    $PicturePath = ‘/tmp/xxxjgjgj.jpg’;//假设这是上传的图片,php放在一个临时文件夹。脚本执行完毕后自动删除了。

    $imgStream = fread(fopen($PicturePath, "r");

    $blob_img = fread(fopen($imgStream, "r"), filesize($PicturePath));

    $sql =” INSERT INTO Images (this_image) VALUES ($blob_img)";

    注:this_image就是数据表中一个blob字段类型的字段

    ================取出展示图片代码

    $result=mysql_query("SELECT * FROM Images WHERE PicNum=$PicNum") or die("Cant perform Query"); $row=mysql_fetch_object($result); Header( "Content-type: image/gif"); echo $row-> this_image;

    总结:处理代码感觉还真比较麻烦。其实,我从来没用过在数据库中以二进制存储图片的做法。我们用得更多的是存储图片的路径,实际图片是在磁盘上保存的。

    据我了解,互联网环境中,大访问量,数据库速度和性能方面很重要。一般在数据库存储图片的做法比较少,更多的是将图片路径存储在数据库中,展示图片的时候只需要连接磁盘路径把图片载入进来即可。因为图片是属于大字段。一张图片可能1m到几m。

    有个原则:图片尽量不要存储在数据库中。这样的大字段数据会加重数据库的负担,拖慢数据库。在大并发访问的情况下很重要。这是一个经验。去看看dba对数据库性能调优方面的分析都能得到这个答案的:就是图片不要存储在数据库中。

    展开全文
  • 关于MySql数据库,相信很多人都不陌生,这是当今最常用的一种关系型数据库,关于MySql的知识也是很丰富的...Innodb的存储格式我们知道,关于Mysql这种关系型数据库,里面保存的数据最终都是要持久化到磁盘文件上面的...
  • hive文件存储格式

    2016-04-13 16:01:42
    HIVE默认存储格式也是最简单的存储格式,即:文本文件格式:textfile, 1.textfile textfile为默认格式 存储方式:行存储 优点:1. 可以任意的分隔符进行分割,  2. 便于查看和编辑,可以直接HDFS查看明文...
  • 关于MySql数据库,相信很多人都不陌生,这是当今最常用的一种关系型数据库,关于MySql的知识也是很丰富的...Innodb的存储格式我们知道,关于Mysql这种关系型数据库,里面保存的数据最终都是要持久化到磁盘文件上面的...
  • (1)块存储、对象存储文件存储 存储方式 技术实现 优势 ... 块存储 ... 裸盘上划分逻辑卷,逻辑卷格式化成任意文件系统 ... 支持多种文件系统,传输速度快,... 在格式的磁盘上存储文件
  • linux 添加物理磁盘后,第一块磁盘一般名为sda,第二块磁盘名为sdb,皆显示/dev 目录下 可进入/dev目录执行命令:ll sd* 查看 其中sda1指是sda磁盘划分第一块分区,sda2是指第二块分区 如果磁盘刚挂载并未...
  • 数据库最终所有的数据(包括我们建的各种表以及表里的数据)都是要存放在磁盘上的文件里的,然后在文件里存放的物理格式就是数据页,那么大量的数据页在磁盘文件里是怎么存储的呢? 首先大家要明白的一点是,大量的...
  •  数据库文件在磁盘上的存储形式:  主数据文件:*.mdf。用来存储数据库的启动信息、存储部分或全部的数据。整个的数据库只能有一个主数据文件  辅助数据文件:*.ndf。用于存储主数据文件未能存储的剩余数据和...
  • 磁盘存储的性能问题

    2021-01-28 20:35:01
    我们现在大部分企业仍然用是机械结构磁盘,如果把消息以随机方式写入到磁盘,那么磁盘首先要做就是寻址,也就是定位到数据所在物理地址,在磁盘上就要找到对应柱面、磁头以及对应扇区;这个过程相对...
  • 在磁盘上是.asset的文件,在project中看到是一个mesh符号的文件,注意,挂载object上必须有mesh组件 public Transform object; private string name; void SaveAsset() { Mesh mesh = object.GetC...
  • 个人理解:要访问存储在磁盘上的数据或是要将数据保存到磁盘上,OS要用到文件系统程序,而文件系统程序是与磁盘的物理特性有关,比如说我要访问的数据是在哪个磁面,哪个磁道的哪个扇区。所以文件系统程序肯定与磁盘...
  • 【Linux】Linux文件文件的存储

    万次阅读 2018-07-31 18:39:51
    从使用和创建文件的用户角度来看,文件磁盘的最小存储单元,用户数据除非在文件中,否则不能保存到磁盘;从进程角度来看,文件是一种进程可以对它进行访问,但独立于进程而存在数据结构,文件信息不会因...
  • 比方说:原本存储在电脑磁盘重要文件,因为格式磁盘永久丢失了。那么,磁盘数据格式化了怎么恢复呢?其实解决这个问题很简单,只需要知道方法和原理即可搞定。所以,接下来小编也将从这两个方法为大家讲解,...
  • 从使用和创建文件的用户角度来看,文件磁盘的最小存储单元,用户数据除非在文件中,否则不能保存到磁盘;从进程角度来看,文件是一种进程可以对它进行访问,但独立于进程而存在数据结构,文件信息不会...
  • linux是最传统的磁盘文件系统(filesystem)使用的是EXT2格式,所以要了解 linux 的文件体统就得从认识EXT2开始,而文件系统建在磁盘上的,因此了解物理组成是重点关注的目标。 整颗圆盘由以下部分组成: 圆形的...
  • 一块磁盘买回来,装到电脑,所有的文件都放在一个盘,显得太乱了, 所以我们要为磁盘分区,这样可以方便我们分类查找存储文件。 一、管理磁盘 添加磁盘的方法昨天我们已经讲过了,这里就不啰嗦了,如果有忘记...
  • 对于计算机病毒的存储结构来说,不同类型的病毒,在磁盘上的存储结构是不同的。 1.磁盘空间的总体划分经过格式化后的磁盘包括:主引导记录区(只有硬盘有)、引导记录区、文件分配表 (FAT)、目录区和数据区。 主 ...
  • 没有RAID程序参与条件下,系统可以识别6块磁盘,并且经过文件系统格式化后,挂载到某个盘符或目录下,供应用程序读写。安装了RAID程序之后,用户通过配置界面,先将两块IDE磁盘做成了一个RAI...
  • 为什么怎么说呢,都是监控是用来事后处理事物的,所以说存储是多么重要的,要想有一个比较稳定的存储,必须要好好规划,我尝试过自定义avi格式存储和mp4格式存储,如果用简单的项目还好没什么问题,但是如果...
  • 由于初次使用 OpenNebula 发现我OpenNebula 挂 新硬盘设置格式 qcow2 后服务器内无法识别...发现服务器加载的文件都是raw的磁盘文件格式,并不是我之前设置qcow2。 解决办法: 高级设置Image mpping d...
  •   存储方式 技术实现 优势 劣势 代表作 块存储 裸盘上划分逻辑卷,逻辑卷格式化成任意文件系统 支持多种文件系统,传输速度快,提供... 在格式的磁盘上存储文件 提供网络共享 网络...
  • 1)Numpy能够读写磁盘上的文本数据或二进制数据。将数组以二进制格式保存到磁盘np.load和np.save是读写磁盘数组数据的两个主要函数,默认情况下,数组是以未压缩的原始二进制格式保存扩展名为.npy的文件中。import ...
  • numpy的文件存储.npy .npz文件详解Numpy能够读写磁盘上的文本数据或二进制数据。将数组以二进制格式保存到磁盘np.load和np.save是读写磁盘数组数据的两个主要函数,默认情况下,数组是以未压缩的原始二进制格式保存...
  • 磁盘分区计算机中存放信息的主要的存储设备就是硬盘,但是硬盘不能直接使用,必须对硬盘进行分割,分割成的一块一块的硬盘区域就是磁盘...主引导记录是磁盘上最前边的一段代码,它负责磁盘操作系统对磁盘进行读写时分区

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,602
精华内容 640
关键字:

文件在磁盘上的存储格式