CaltechCS122 笔记:Assignment 1: NanoDB Set-Up and Storage Layer

Assignment 1: NanoDB Set-Up and Storage Layer

NanoDB 是加州理工大学 Caltech CS122 课程使用的教学数据库系统

task

  1. Add support for tuple updates and deletion in NanoDB
  2. Add code to pin/unpin pages and tuples for proper buffer management
  3. Improve the insert performance of the NanoDB heap file implementation, without substantially increasing the overall file size

DataStruct

如图所示 HeapFile 包含如图所示类:

img

  • HeapFilePageTuple 定义了 Tuple 的数据结构

  • DataPage 的结构如下图所示:

img

img

如图所示,我们可以在每个 datapage 的结尾预留 2 个 bytes 的空间来存储当前 dataPage 的 freeSpace 的大小。在开头的 2 个 bytes 存储当前 page 中有多少个 tuple。每个 slot 中存储了一个 tuple 的起始地址。

  1. 因此,每个 page 的 getTupleEnd 的值要减 2
  2. 与此同时,当我们插入 tuple 时,还要更新此 DataPage 的空闲空间记录区域的值。
  3. 当删除 tuple 时,也要更新空闲空间记录区域的值。
  4. 当初始化一个 datapage 时,空闲空间记录区域的值也要进行初始化,所以当初始化一个 DataPage 时,其大小初始化为 8192 - 4,即每个 page 的前后 2 个 byte 都不存放数据使用。
  • HeapTupleFile 的结构:

side 中给出了 2 种方法

List of Non-Fill Blocks

img

Free-Space Bitmap

img

在这个 lab 中 选择了 Free-Space Bitmap 方法进行布局,File 中的 page 布局如下图所示:

img

其中 block 0 为 HeaderPage, block 1 为 DataPage,但是这个 page 是存放标识这个 File 中 block 存储情况的 bitmap。所以真正的数据是从 block2 开始存放的。

重要方法:
getFirstTuple 方法:在文件中找出第一个满足 tuple,并构造 HeapFilePageTuple 对象。

storageManager.loadDBPage(file, pageno) 使用这个方法,可以得到给定 file 和给定 pageno 的 dbPage。

  • HeapTupleFileManager

用于创建/删除 db 文件。

task1 support for tuple updates and deletion

执行 update tuple 的逻辑为调用 HeapTupleFile 中的 updateTuple 方法将 tuple 中的给定列值进行修改。如下图所示:

img

其中 value 值可以是 null,也可以是 int,float 这样的定长数据类型,或者 varchar 这样的变长数据类型。下图为 setColumnValue 方法中的片段,由代码可以看出,对 value null 和非 null 值是分开处理的:

img

value 为 null 值

  • 对 column_idx 所指定的 column 设置 null 值
  1. 如果该 column 本身就是 null 值,直接返回

  2. 如果本身的 column 不为 null 值。需要进行如下的处理:

2.1. 将 tuple 中的 bitmap 中该列的标识置为空。
2.2. 删除该列的数据(会对数据进行移动)
2.3. 更新 valueOffset 的内容

value 为非 null 值

当进行 update 时,如果 set 的值为非 null,需要考虑以下几个方面:

  1. 原来的列是一个空值,或者是一个变长值

1.1. 分配一块空间在 datapage 中
1.2. 调用 writeNonNullValue 方法
1.3. 更新相关的数据结构

  1. 原来的列是一个非空值,且是一个定长的数据类型

对于第二种情况,直接调用 writeNonNullValue,更新相关数据结构。

对于空间的开辟

  1. 当原值为 NULL 时需要开辟新的空间
  2. 当原值为 varchar 且空间不够时需要开辟新的空间,当空间多出来的时候,需要回收空间。

task2 pin/unpin pages and tuples for proper buffer management

lab1 的第二部分是实现充分利用空间的 bpm,当前所给出的 bpm 代码 pin/unpin 的调用存在问题,当进行大规模数据的 insert 操作时,会出现空间不够用的问题。

需要 unpin 的几个部分

  1. HeaderPage
  2. QueryPlan 处理完的 tuple
  3. 在 SelectNode 中不满足 predicate 的 tuple

修改

  1. HeapFileManager
  2. HeaderPage
  3. DataPage

task3 improve the insert performance

当前 addTuple() 的执行流程

  1. 从 PageNo = 1 的 page 开始寻找能容纳当前 tupleSize 的 datapage
  2. 在 datapage 中,从 slot0 开始,寻找合适的插入位置。

由上述流程可知,其 insert 操作的时间复杂度为 O(n^2),现在即使存储了每个 page 的空闲空间的大小,在 insert 的过程中,还是会要遍历每个 page 到内存,所以为了提高 insert 的执行效率,应尽量减少从磁盘读 page 的次数。

优化思路:

  1. 查找 tuplefile 中的 bitmap, 从 page2 开始找到非空 page。
  2. loadDBPage(file, pageno) 使用这个方法得到该 pageno 的 page,减少了 seek 的次数。
  3. 计算这个 page 的空闲空间,如果空间不够,继续寻找。
  4. 如果所有的 pageno 都没有合适的空间存储该 tuple。
  5. 申请一个新的 page 并将 tuple 放入其中,更新相关数据结构。

Result

img

Note

为什么在 DataPage 中的 Tuple 要从后往前存?

便于空间回收,当某个 tuple 被删除时,可以将其之后插入的 tuple 向后移动,slot 向前移动确定的大小,并修部分 slot 内的值即可。
如果在 slot 之后插入,那么每当删除一个 tuple,由于部分 slot 的移动,导致其后的所有 tuple 都需要移动,同时剩余的 slot 中的内容也都需要修改。

什么条件来决定 Page 已经满了?

当 page 中的空闲空间不能在插入一个 Tuple 了(可以通过 Tuple 的 schema 来计算这个 Tuple 所占空间的大小)。

Draft

CREATE TABLE heap_update (a INTEGER, b BIGINT, c CHAR(7), d DOUBLE, e VARCHAR(20), f FLOAT);

INSERT INTO heap_update VALUES (35, 521, 'abcd', 3.14, 'goodbye', 2.71828);
INSERT INTO heap_update VALUES (6177281, -405691, 'fghi', 6.28, 'puce', 54.669);
INSERT INTO heap_update VALUES (-403662, 928032810, 'qrstu', 965.2323, 'alongerstring', -31.2115);

SELECT * FROM heap_update;

+---------+-----------+-------+----------+---------------+----------+
| a       | b         | c     | d        | e             | f        |
+---------+-----------+-------+----------+---------------+----------+
|      35 |       521 | abcd  |     3.14 | goodbye       |  2.71828 |
| 6177281 |   -405691 | fghi  |     6.28 | puce          |   54.669 |
| -403662 | 928032810 | qrstu | 965.2323 | alongerstring | -31.2115 |
+---------+-----------+-------+----------+---------------+----------+

-- 构造好用于测试的Table,如上表。

-- 代码中没有进行置空的update语句,我们需要进行修改。
-- 增加一行tuple,以免和原有的测试用例冲突
INSERT INTO heap_update VALUES (999, 100, 'tttt', 0.123, 'ccc', 1.456);

UPDATE heap_update SET b = NULL WHERE a = 999;


+---------+-----------+-------+----------+---------------+----------+
| a       | b         | c     | d        | e             | f        |
+---------+-----------+-------+----------+---------------+----------+
|      35 |       521 | abcd  |     3.14 | goodbye       |  2.71828 |
| 6177281 |   -405691 | fghi  |     6.28 | puce          |   54.669 |
| -403662 | 928032810 | qrstu | 965.2323 | alongerstring | -31.2115 |
|     999 |      null | tttt  |    0.123 | ccc           |    1.456 |
+---------+-----------+-------+----------+---------------+----------+
UPDATE heap_update SET e = NULL WHERE a = 999;

UPDATE heap_update SET b = 92281965 WHERE a = 6177281;
UPDATE heap_update SET c = 'm' WHERE a = 35;
UPDATE heap_update SET a = 771 WHERE b = 521;

SELECT * FROM heap_update;

+---------+-----------+-------+----------+---------------+----------+
| a       | b         | c     | d        | e             | f        |
+---------+-----------+-------+----------+---------------+----------+
|     771 |       521 | m     |     3.14 | goodbye       |  2.71828 |
| 6177281 |  92281965 | fghi  |     6.28 | puce          |   54.669 |
| -403662 | 928032810 | qrstu | 965.2323 | alongerstring | -31.2115 |
+---------+-----------+-------+----------+---------------+----------+

-- Next, try modifying multiple fixed-size things at once.

UPDATE heap_update SET d = 55.55, f = -43.21 WHERE a = 771;
UPDATE heap_update SET b = -43, c = 'q', d = -3.32 WHERE a = -403662;

SELECT * FROM heap_update;

+---------+----------+------+-------+---------------+----------+
| a       | b        | c    | d     | e             | f        |
+---------+----------+------+-------+---------------+----------+
|     771 |      521 | m    | 55.55 | goodbye       |   -43.21 |
| 6177281 | 92281965 | fghi |  6.28 | puce          |   54.669 |
| -403662 |      -43 | q    | -3.32 | alongerstring | -31.2115 |
+---------+----------+------+-------+---------------+----------+

-- Next, try modifying variable-sized stuff and see what happens.

UPDATE heap_update SET e = 'hello' WHERE a = 771;

+---------+----------+------+-------+---------------+-------------+
| a       | b        | c    | d     | e             | f           |
+---------+----------+------+-------+---------------+-------------+
|     771 |      521 | m    | 55.55 | hello         | 7.456089E34 | -- 这一行数据出现了错误
| 6177281 | 92281965 | fghi |  6.28 | puce          |      54.669 |
| -403662 |      -43 | q    | -3.32 | alongerstring |    -31.2115 |
+---------+----------+------+-------+---------------+-------------+



UPDATE heap_update SET e = 'goodeveningsir' WHERE a = 6177281;
SELECT * FROM heap_update;


UPDATE heap_update SET b = NULL WHERE a = 771;
UPDATE heap_update SET e = NULL WHERE a = 6177281;
UPDATE heap_update SET d = NULL, f = NULL WHERE a = -403662;


UPDATE heap_update SET e = 'whyohwhy', b = NULL WHERE a = 6177281;
UPDATE heap_update SET d = 5.32, f = NULL WHERE a = -403662;
UPDATE heap_update SET c = NULL, b = 6543210 WHERE a = 771;

posted on   LambdaQ  阅读(100)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示