Lecture 3 Notes

2026/5/21 2296 words 9 min read

1.Storage

在这门课中,我们关注的是一种「面向磁盘(disk-oriented)」的 DBMS 架构,假设数据库的主要存储位置在非易失性磁盘(non-volatile disk)上。

info

  • CPU:执行计算与指令的核心部件,速度极快但几乎不用于存储数据。
  • 内存(memory):CPU 直接访问的工作区,支持快速随机访问但断电会丢失数据。
  • SSD:基于闪存的非易失性存储设备,速度较快且无机械结构。
  • HDD:传统机械硬盘,依赖物理旋转读写,速度较慢但容量大且成本低)。


在存储层次结构(storage hierarchy)中,最接近 CPU 的设备通常是最快的,但也是最小且最贵的。随着距离 CPU 越来越远,storage devices 的容量变大,但速度会变慢,且每 GB 的成本也会下降。

1.1 易失性设备(Volatile Devices)

Volatile 意味着设备在断电后不会保留其数据。因此,存储在这些设备上的数据会丢失。

  • Volatile devices 支持按字节地址进行快速随机访问,意味着程序可以直接跳转到某个字节地址并读取数据(例如:DRAM)。
  • 在本课程中,我们将这类设备统称为 memory。

1.2 非易失性设备(Non-Volatile Devices)

Non-volatile devices 能够在机器关闭或断电后依然保留数据。

  • Non-volatile devices 是按块(block)或页面(page)进行寻址的。也就是说,程序在读取某个特定偏移量(offset)的数据时,需要先将包含该数据的 4KB page 加载到 memory 中。
  • Non-volatile storage devices 通常在顺序访问(sequential access)性能上表现更好(读取连续的数据块),这是因为 HDD 和 SSD 等设备的架构更适合 sequential read。

在本课程中,我们将其统称为 disk。我们不会对 SSD 和 HDD 做出显著区分。

2.Disk-Oriented DBMS Overview

数据库存储在 disk 上,数据以 page 为单位组织,其中第一个 page 通常是目录页(directory page)。
为了操作数据,DBMS 必须先将数据加载到 memory 中。
DBMS 通过缓冲池(buffer pool) 管理 disk 与 memory 之间的数据移动。

  • 执行引擎(execution engine)负责执行 queries
  • execution engine 向 buffer pool 请求所需的 page
  • buffer pool:
    • 将 page 从 disk 加载到 memory
    • 返回该 page 在 memory 中的 pointer
  • 缓冲池管理器(buffer pool manager)保证:
    • 在执行期间,该 page 始终驻留在 memory 中

3.DBMS vs. OS

DBMS 的设计目标之一是支持超过 memory 容量的数据(data > memory)
由于 disk I/O 成本高,需要避免因 disk access 导致系统阻塞(stall)。
因此希望在等待 disk data 时,仍能继续执行其他 queries。
该设计类似于虚拟内存(virtual memory)

  • 提供大的地址空间(address space)
  • 由 OS 在 disk 与 memory 之间调度 page

一种实现方式是使用 mmap(memory mapping)

  • 将文件(file)映射到进程地址空间(process address space)
  • 由 OS 负责 page 在 disk 与 memory 之间的移动

问题:

当发生 page fault 时,process 会被阻塞(blocked)

因此 DBMS 通常不使用 mmap,不希望由 OS 控制数据移动。
DBMS 更了解:

  • 数据访问模式(access pattern)
  • query execution
    OS 采用通用策略,无法针对数据库优化(The operating system is not your friend)
    我们更可能这样使用 OS:
  • madvise:提示 access pattern
  • mlock:防止 memory 被换出(swap)
  • msync:将 memory data 刷回 disk

出于正确性和性能的考虑,我们不建议你在 DBMS 中使用 mmap。
尽管该系统具有一些看似 OS 可以提供的功能,但让 DBMS 自行实现这些过程可以带来更好的控制和性能。

4.File Storage

最基本的 DBMS 将数据库以 file 的形式存储在 disk 上。有些 DBMS 使用文件层级结构(file hierarchy),有些则使用单个 file(例如 SQLite)。
OS 对这些 files 的内容一无所知。只有 DBMS 才知道如何解读它们的内容,因为这些 files 是以 DBMS 特有的方式编码的。
DBMS 的存储管理器(storage manager)负责管理数据库的 files。它将 file 表示为 pages 的集合。它还跟踪 pages 中已读取和写入的数据,以及这些 pages 中的可用空间(free space)。

5.Database Pages

DBMS 将数据库组织为一个或多个 files,并以固定大小的数据块(fixed-size blocks) 进行管理,这些 blocks 称为 pages。

  • 一个 page 可以包含不同类型的数据(tuples、indexes 等)
  • 大多数系统不会在同一个 page 中混合不同类型的数据
  • 一些系统要求 page 是自包含(self-contained) 的:
    • 即读取一个 page 所需的全部信息都在该 page 内

每个 page 都有唯一标识:Page ID
若数据库是单 file:page ID 可以是 file offset

  • page ID 的唯一性可能作用范围:
    • DBMS 实例级
    • 数据库级
    • 表级

大多数 DBMS 使用 indirection layer,将 page 映射到 file path 和 file offset。
而上层系统是只会请求 page number,然后由 storage manager 解析为具体位置。

大多数 DBMS 使用 fixed-size page,以避免支持 variable-size page 带来的复杂性:

  • 删除 page 可能导致 file 出现「空洞」(hole)
  • 难以重新利用

DBMS 中存在三种 Page 概念:

  1. 硬件页(hardware page):通常 4KB
  2. 操作系统页(OS page):通常 4KB
  3. 数据库页(database page):1–16KB

面向只读(read-only)场景的系统,通常使用更大的 page。

Storage devices 保证对 hardware page 大小的写入操作具有原子性(atomicity)。如果 hardware page 大小为 4 KB,而系统尝试向 disk 写入 4 KB 的数据,那么要么全部写入,要么一个也不写入。这意味着,如果 database page 大于 hardware page,DBMS 就必须采取额外的措施来确保数据安全写入,因为程序可能在系统崩溃(system crash)时正在将 database page 写入 disk。

6.Database Heap

DBMS 在 disk 上定位所需 page 有多种方式,其中一种是堆文件(heap file)。
heap file 指的是一种 无序(unordered) 的 page 集合,其中 tuples 以随机顺序存储。

给定一个 page_id,DBMS 可以通过两种方式在 disk 上定位该 page:使用 page 的链表(linked list),或者使用页目录(page directory)。
在 linked list 方案中,系统维护一个 header page,其中包含两类指针:

  • 指向空闲页(free pages),
  • 指向数据页(data pages)。

当 DBMS 需要查找某个特定 page 时,必须沿着 data page linked list 进行顺序扫描(sequential scan),直到找到目标 page。

在 page directory 方案中,DBMS 维护一类特殊的 page,称为 page directory,用于记录 data pages 的位置(location)、每个 page 的 free space、free/empty pages 以及 page 的类型(page type)。这些 directory pages 中,每个数据库对象(database object)都有对应的一条记录(entry)。

7.Page Layout

每一个 page 都包含一个 header,用于记录该 page 的元数据(meta-data)。这些信息通常包括:

  • page size
  • checksum
  • DBMS version
  • transaction visibility

以及是否要求 self-containment(某些系统如 Oracle 会要求)。

一种最直观的数据组织方式是:记录当前 page 中存储了多少 tuples,并在每次插入新 tuple 时,将其追加到 page 的末尾。然而,这种方式在 tuples 被删除或存在变长属性(variable-length attributes)时会出现问题。

因此,DBMS 通常采用两种主要的 page layout 方式:

  • slotted pages
  • log-structured。

slotted pages 结构中,page 内部维护一个 slot 到 offset 的映射关系,这是当前 DBMS 中最常见的实现方式。page header 会记录已使用 slot 的数量、最后一个已使用 slot 的起始位置,以及一个 slot array,该数组用于记录每个 tuple 起始位置的 offset。

在插入新 tuple 时,slot array 从 page 的开头向后增长,而 tuple data 则从 page 的末尾向前增长。当 slot array 与 tuple data 区域相遇时,page 被认为已满。

8. Tuple Layout

A tuple 本质上是一个字节序列(byte sequence),这些 bytes 不一定是 contiguous 的。DBMS 的工作就是将这些 bytes 解释为 attribute types 和 values。

8.1 Tuple Header

包含关于 tuple 的 meta-data。

  • 用于 DBMS concurrency control protocol 的 visibility information,即哪个 transaction 创建 / 修改了该 tuple 的信息,课程后面会讲。
  • 用于 NULL values 的 Bit Map。
  • 注意:DBMS 不需要在这里存储关于 database schema 的 meta-data。

8.2 Tuple Data

实际的 attribute data。

  • Attributes 通常按照你创建 table 时指定的顺序存储。
  • 大多数 DBMS 不允许一个 tuple 超过一个 page 的大小。

8.3 Unique Identifier

  • 数据库中的每个 tuple 都会被分配一个 unique identifier。
  • 最常见的形式:page id + (offset or slot)
  • Application 不应该依赖这些 ids。

8.4 Denormalized Tuple Data

如果两个 tables 之间存在关联,DBMS 可以提前将它们 “pre-join”,使它们最终位于同一个 page 上。这样读取会更快,因为 DBMS 只需要加载一个 page,而不是两个 separate pages。

不过,这也会让 updates 更昂贵,因为 DBMS 需要为每个 tuple 分配更多空间。