CMU15445-lecture4
第四课:数据库存储(第二部分)
1 日志结构存储
一些与插槽页设计相关的问题有:
- 碎片化:删除元组可能会在页面上留下空隙,使其无法完全利用。
- 无用的磁盘IO:由于非易失性存储的块定向性特性,更新一个元组需要获取整个块。
- 随机磁盘 I/O:磁盘读取器可能要跳到 20 个不同的位置来更新 20 个不同的元组,这可能非常慢。
如果我们在一个只允许创建新页面而不允许覆写的系统上工作,那该怎么办呢?日志结构存储模型基于这个假设,并解决了上述一些问题。
日志结构存储:DBMS不是存储元组,而是仅存储元组的更改日志记录。DBMS将新的日志条目追加到内存缓冲区中,而不检查之前的记录,然后按顺序将更改写入磁盘。
- 记录包含了元组的唯一标识符、操作类型(PUT/DELETE)以及对于PUT操作来说,元组的内容。
- 要读取一条记录,DBMS会逆向扫描日志文件,从最新的到最旧的,以找到元组的最新内容。
- 快速写入,潜在的读取缓慢。磁盘写入是顺序进行的,并且现有页面是不可变的,这减少了随机磁盘输入/输出。适用于只追加存储。
- 为了避免读取时间过长,数据库管理系统可以通过索引(用于簿记)来让它能够跳转到日志中的特定位置。
- 日志最终会变得很大。数据库管理系统可以定期压缩日志,仅保留跨多个页面的每个元组的最新更改。
- 在压缩之后,不再需要排序,因为每个元组只有一个,所以数据库管理系统可以按照ID进行排序以进行更快的查找。这被称为排序字符串表(Sorted String Tables,SSTables)。
- 在通用整理中,任何日志文件都可以一起整理。在层级整理中,最小的文件是 level 0。Level 0 文件可以整理成更大的 level 1 文件,level 1 文件可以整理成 level 2 文件,依此类推。
- 缺点是压缩成本昂贵,同时也会导致写放大(对于每个逻辑写入,可能存在多次物理写入)。
2 索引组织存储
注意,无论是面向页面的存储还是日志结构化存储,都依赖额外的索引来查找单个元组,因为表本身是无序的。在索引组织存储方案中,数据库管理系统直接将表的元组作为索引数据结构的值进行存储。数据库管理系统会使用类似分槽页面的页面布局,并且通常按照键值将元组在页面上进行排序。
3 数据表示
元组中的数据本质上只是字节数组,并且不会跟踪属性的种类。这是由DBMS负责指导如何跟踪并解释这些字节。数据表示方案是DBMS用于存储值的字节的方式。
DBMSs希望确保元组是字对齐的,这样CPU就可以在访问时不会出现任何意外的行为或额外的工作。通常采用两种方法:
- 填充:在属性后添加空位以确保元组对齐字边界。
- 重新排序:交换物理布局中属性的顺序,以确保它们对齐。
元组中可以存储五种高级数据类型:整数、可变精度数、固定小数点精度数、可变长度值以及日期/时间。
整数
大多数数据库管理系统(DBMS)使用IEEE-754标准规定的”C/C++”的”本地”数据类型来存储整数。这些值是固定长度的。
例如:INTEGER,BIGINT,SMALLINT,TINYINT。
可变精度数
这些是不精确和可变精度的数值类型,使用IEEE-754标准规定的“本地”C/C++类型。这些值也是固定长度的。
与任意精度的数字相比,变精度数字的运算速度更快,因为CPU可以直接在其上执行指令。然而,在进行计算时可能会产生舍入误差,因为某些数字无法精确表示。
例如:FLOAT,REAL。
固定小数点精度数
这些是具有任意精度和小数位的数字数据类型。它们通常以精确、可变长度的二进制表示形式存储(几乎像字符串一样),并附带额外的元数据,告诉系统数据的长度和小数点位置等信息。
当舍入误差是不可接受的时候,使用这些数据类型,但数据库管理系统会因为追求精确性而付出性能的代价。
例子:NUMERIC,DECIMAL。
可变长度值
这些代表了任意长度的数据类型。它们通常以一个头部存储,以跟踪字符串的长度,以便轻松跳转到下一个值。它还可能包含数据的校验和。
大多数数据库管理系统不允许元组的大小超过一个页面的大小。那些允许的系统会将数据存储在特殊的“溢出”页面上,并使元组包含对该页面的引用。这些溢出页面可以包含对其他溢出页面的指针,直到所有数据都可以存储。
一些系统可以让您将这些大值存储在外部文件中,然后元组将包含对该文件的指针。例如:如果数据库存储图片信息,DBMS可以在外部文件中存储这些照片而不是占用大量的数据库空间。这个的一个不足之处是数据库管理系统无法操作这个文件的内容。因此,它没有持久性或事务保护。
例如:VARCHAR、VARBINARY、TEXT、BLOB。
日期和时间
日期/时间的表示方式因不同系统而异。通常,它们被表示为自Unix纪元以来的某个时间单位(微/毫)秒。
示例:TIME、DATE、TIMESTAMP。
空数据类型
在数据库管理系统中,有三种常见的方法来表示空值。
- 空列位图头:在一个集中的头部中存储一个位图,指定哪些属性是空值。这是最常见的方法。
- 特殊值:为数据类型指定一个值来表示空值(例如,INT32的最小值)。
- 每个属性的空标志:存储一个标志,标记一个值是否为空。这种方法不推荐使用,因为它不是存储效率高。对于每个值,数据库管理系统必须使用多个位来避免破坏字对齐。
4 系统目录
为了使DBMS能够解读元组的内容,它维护一个内部目录来告诉它有关数据库的元数据。
元数据内容:
- 数据库所拥有的表和列,以及这些表上的索引
- 数据库的用户及其权限
- 表的统计信息以及其中包含的内容(例如,属性的最大值)。
大多数数据库管理系统(DBMS)将其目录存储在其表格所使用的格式内部。它们使用特定的代码来”引导”这些目录表。