Chapter 13 Data Storage Structures
- [13.2 File Organization](#13.2 File Organization)
-
- [13.2.0 Introduction](#13.2.0 Introduction)
- [13.2.1 Fixed-Length Records](#13.2.1 Fixed-Length Records)
- [13.2.2 Variable-Length Records](#13.2.2 Variable-Length Records)
- [13.2.3 Storing Large Objects](#13.2.3 Storing Large Objects)
- [13.3 Organization of Records in Files](#13.3 Organization of Records in Files)
-
- [13.3.0 Introduction](#13.3.0 Introduction)
- [13.3.1 Heap File Organization](#13.3.1 Heap File Organization)
- [13.3.2 Sequential File Organization](#13.3.2 Sequential File Organization)
- [13.3.3 Multitable Clustering File Organization](#13.3.3 Multitable Clustering File Organization)
- [13.3.4 Partitioning](#13.3.4 Partitioning)
13.2 File Organization
13.2.0 Introduction
这一节主要介绍数据库中的数据(或者说记录)在文件的最小组成单位,磁盘块 中的组织形式,我们学过操作系统的都知道,文件在存储容器(磁盘或硬盘)中以块 的形式存在,但是数据库中的记录大小可能很大。为了起到循序渐进的介绍效果,我们先假设所有记录的大小都小于一个块的大小 ,大小比较大的记录的处理方法会在13.2.2节介绍(大致就是分开来存储,并且增加索引方便重新拼接);同时,我们需要规定,一条记录完整包含于一个块中 ,就是说一个比块小的记录不会分开存储。
由于每条记录的大小也可能不一,一般有两种组织方式,一种是用多种文件 ,每一种文件存一种大小的记录;另一种就是支持变长记录的结构化文件 ;在这里,我们先考虑使用前者存放固定长度的记录 ,后面再介绍在这种组织方式下如何实现变长记录的存储。
13.2.1 Fixed-Length Records
这一小节主要介绍了固定长度记录存储模型 的两个问题以及解决思路。
定长记录存储模型的两个问题:
- 记录长度与块大小不匹配(不整除),可能导致某些记录分开在两个块中存放
- 记录删除时如何处理
第一个问题的解决方法很简单,我们让不整除的块最后的空间浪费 即可,具体来说,若每个块长度为X,记录长度为Y,则每个块只存放 ⌊ X / Y ⌋ \lfloor X / Y \rfloor ⌊X/Y⌋条记录。
对于第二个问题,暴力的解决方法是将被删除记录后面的所有记录往前移动 ,这种做法很影响效率,肯定不行。我们可以将被删除的记录用链表串起来,形成一个空闲块链表 ,类似下图。
这种链表的做法也有一定的问题,就是如果记录是变长的,那么空闲链表中的空闲块可能没法满足新插入的记录长度 或者插入的记录长度比空闲块大小小得多,这个问题在下一节探讨。
13.2.2 Variable-Length Records
这一小节也是解决两个问题:
- 记录存储结构如何设计使得能够简单的提取出每一个字段,即使存在变长字段
- 变长记录在block中的存储结构如何设计使得能够简单的提取出block中的每一条记录
首先看第一个问题,采用的方法是将记录中的变长部分与定长部分分开,一条记录分为两部分,称为定长区与变长区。定长区 存放定长字段内容 与变长字段的偏移量和长度 ,变长区 则存放变长字段的实际内容 ,如下图。在定长区与变长区中,会有若干字节存放一个bitmap
,用于记录哪些字段是空的 。在某些数据库的实现中,bitmap
会安排在记录存储位置的最前方,而空字段将不再用另外的空间存储(相当于只用bitmap
中的一个位来存储空字段),在某些场景下比较节省空间(如空字段很多的记录 )
对于第二个问题,就是若干记录在block中的组织形式,一般采用一种叫slotted-page
的结构,大致如下图所示。在block的最前面,会存放一个Header
,用于记录一些元数据:
- 头部的Entries数(我理解就是block中当前存放的记录数)
- 空闲区尾部的位置
- Entries数组,每个元素表示一条记录的位置和长度
从下图也可以看出,空闲区被夹在中间,当有新纪录插入时,空闲区尾部会被分配给这个新纪录 ,同时更新Header
;当有某个记录被删除时,在删除记录前面的记录需要被移动,将空闲区合并起来 (这里感觉怪怪的,但是书里说因为一个块不会很大,4KB或者8KB,所以这个移动不怎么影响效率)。
13.2.3 Storing Large Objects
这一节讲的不是很细,大概聊了下庞大对象的存储方式,要么以文件形式存储在数据库管理的文件区域 ,要么以文件结构形式存放在数据库中并由数据库管理。后者用B+树来维护,在14.4.1节会详细介绍。
13.3 Organization of Records in Files
13.3.0 Introduction
本节主要介绍了一些常用的文件组织结构:
- Heap File Organization:堆叠式结构,记录无序,就是随便放
- Sequential file organization:序列结构,记录有序,但是维护效率低
- Multitable clustering file organization:一个文件甚至一个盘块,可以存放多个关系的记录,便于一些关系的join操作
- B±tree file organization:B+树结构,记录有序,维护效率高
- Hashing file organization:哈希结构,和索引结构有关
本节介绍前三个结构,后面两个会在14.4.1和14.5介绍。