其他分享
首页 > 其他分享> > MIT6.830 lab1 SimpleDb

MIT6.830 lab1 SimpleDb

作者:互联网

MIT6.830 lab1 SimpleDb

整个实验一共有6个lab,通过每一个lab的代码去实现一个简单的数据库,主要有:数据库的组织架构(字段、元组、模式、buffer pool等)、CRUD的实现、查询优化、事务与并发控制、崩溃与故障恢复。

SimpleDB consists of:

  • Classes that represent fields, tuples, and tuple schemas;
  • Classes that apply predicates and conditions to tuples;
  • One or more access methods (e.g., heap files) that store relations on disk and provide a way to iterate through tuples of those relations;
  • A collection of operator classes (e.g., select, join, insert, delete, etc.) that process tuples;
  • A buffer pool that caches active tuples and pages in memory and handles concurrency control and transactions (neither of which you need to worry about for this lab); and,
  • A catalog that stores information about available tables and their schemas.

lab1主要是实现了整个数据库的整体架构,主要有这几个部分:Tuple(元组)、TupleDesc(table的metadata)、catalog(该数据库并没有过度区分catalog和schema,可以看成是一个schema)、BufferPool(缓冲池)、HeapPage(数据页)、HeapFile(disk上的文件)、SeqScan(全表顺序扫描)。

lab1要完成:
1.Tuple:元组,数据库上把一个有n列的table称作n元组,一个Tuple有多个字段。通俗来讲,一条记录就是一个元组,在该实验中体现为一个Tuple类的实例。

2.TupleDesc:TupleDesc用来表示一个元组的描述信息,更准确来说应该是一个表的描述信息;

3.Catalog:Catalog是仅次于DataBase的抽象概念,一个DataBase可以有多个Catalog,一个Catalog有多个Schema,一个Schema有多张table。

4.BufferPool:BufferPool的基本单位是Page,每次从磁盘中(这里表现为DbFile)读取数据页到BufferPool,在数据库上的crud操作都是在Buffer Pool的Page中进行的(所以有脏页、故障恢复等)。该数据库的BufferPool默认是缓冲50个Page,每个Page的默认大小是4096bytes即4kb。

5.HeapPage与HeapFile:HeapPage是Page接口的实现,是以顺序逻辑组织数据的一张数据页(后续会用b+树实现来替代),crud操作都是在Page上进行的。HeapPage既是BuffeerPool的基本单位也是HeapFile的基本单位。HeapFile是DbFile接口的实现,与磁盘中的文件交互,该数据中一张表的所有数据就是存到DbFile的File属性中,即一个磁盘的文件就是一张表的所有数据。

6.SeqScan:全表顺序扫描的实现,相当于select * from table.

Exercise1 Fields and Tuples

Tuples in SimpleDB are quite basic. They consist of a collection of Field objects, one per field in the Tuple. Field is an interface that different data types (e.g., integer, string) implement. Tuple objects are created by the underlying access methods (e.g., heap files, or B-trees), as described in the next section. Tuples also have a type (or schema), called a tuple descriptor, represented by a TupleDesc object. This object consists of a collection of Type objects, one per field in the tuple, each of which describes the type of the corresponding field.

1.Tuple:

元组,数据库上把一个有n列的table称作n元组,一个Tuple有多个字段。通俗来讲,一条记录就是一个元组,在该实验中体现为一个Tuple类的实例。一个Tuple由以下部分组成:a.TupleDesc:该元组的描述信息;b.fields:该记录各个字段的类型与值; c.RecordId:该记录在磁盘的位置。
Tuple.java

**2.**TupleDesc:

TupleDesc用来表示一个元组的描述信息,更准确来说应该是一个表的描述信息,TupleDesc就是tuple的schema

TupleDesc.java

3.Field:

SimpleDB中元组中字段值的接口。

Field.java

4.Type

在SimpleDB中表示类型的类。 类型是这个类定义的静态对象; 因此,Type构造函数是私有的。 枚举类实现了INT_TYPE 和 STRING_TYPE

Type.java

5.总结

元组是非常基本的由"Field"对象的集合组成,在"元组"中每个字段一个。"字段"是不同数据类型(例如,整数,字符串)实现的接口。"元组"对象由底层访问方法(例如,堆文件或 B 树)创建。元组还具有一个类型(或架构),称为_tuple descriptor_(元组描述),由"TupleDesc"对象表示。此对象由"Type"对象的集合组成,元组中每个字段一个,每个对象描述对应的类型‎‎字段。

Exercise 2 Catalog

The catalog (class Catalog in SimpleDB) consists of a list of the tables and schemas of the tables that are currently
in the database. You will need to support the ability to add a new table, as well as getting information about a
particular table. Associated with each table is a TupleDesc object that allows operators to determine the types and
number of fields in a table.

The global catalog is a single instance of Catalog that is allocated for the entire SimpleDB process. The global
catalog can be retrieved via the method Database.getCatalog(), and the same goes for the global buffer pool (
using Database.getBufferPool()).

exercise2主要是实现Catalog.java这个类,这里的关键是在Catalog里实现一个Table类,来存放一张表格的信息;然后一个CataLog有多张表格,在Catalog里我们可以用map来存储tableid与table的映射关系,一个file对应一个table。

1.Catalog.java

Catalog跟踪数据库中所有可用的表及其关联的模式。

目前,这是一个存根目录,在使用它之前,用户程序必须用表填充它——最终,它应该转换为从磁盘读取目录表的目录

2.总结

Catalog是仅次于DataBase的抽象概念,一个DataBase可以有多个Catalog,一个Catalog有多个Schema,一个Schema有多张table,不过该数据库没有太过区分这三个概念,而在MySQL中也是用Schema来表示整个数据库包含的多张table。该lab中实现了一个Table类,并在Catalog类中使用一个HashMap来存放table id与table的映射关系。table 中的元素为file:表文件,name:表名,pkeyField:主键名。

Exercise3 BufferPool

The buffer pool (class BufferPool in SimpleDB) is responsible for caching pages in memory that have been recently read from disk. All operators read and write pages from various files on disk through the buffer pool. It consists of a fixed number of pages, defined by the numPages parameter to the BufferPool constructor. In later labs, you will implement an eviction policy(淘汰策略). For this lab, you only need to implement the constructor and the BufferPool.getPage() method used by the SeqScan operator. The BufferPool should store up to numPages pages. For this lab, if more than numPages requests are made for different pages, then instead of implementing an eviction policy, you may throw a DbException. In future labs you will be required to implement an eviction policy.

lab1无需实现淘汰策略,主要是实现getPage方法。根据PageId来查找BufferPool中有无该数据页,如果有直接返回,如果没有就从磁盘中获取,存入BufferPool中。其中BufferPool的容器是用map来存Page的,以pid的hashcode与Page建立映射关系。

1.BufferPool.java:
2.总结

BufferPool管理将页面从磁盘读写到内存。 访问方法调用它来检索页面,它从适当的位置获取页面。

BufferPool也负责锁; 当事务获取页面时,BufferPool检查该事务是否具有读/写页面的适当锁。

lab1只需要实现getpage这一个方法且后续还需要不断地重构,因此比较简单

Exercise 4 HeapFile access method

对象被排列成一组页面,每个页面由固定数量的字节组成,用于存储‎‎元组(由常量定义),包括一个标头。在 SimpleDB 中‎
‎,数据库中的每个表都有一个对象(一个HeapFile对应一张表)。中的每个页面都排列成一组槽,每个‎‎槽可以容纳一个元组(SimpleDB 中给定表的元组大小相同)。除了这些槽之外,‎每个页面都有一个标头,该标头由一个位图组成,每个元组槽有一个位。如果与特定‎‎元组对应的位为1,则表示该元组有效;如果为 0,则元组无效(例如,已被删除或从未初始化过‎
‎。对象页是实现接口的类型。‎页‎‎存储在缓冲池中,但由‎‎HeapFile‎‎类读取和写入。‎HeapFileBufferPool.DEFAULT_PAGE_SIZEHeapFileHeapFileHeapFileHeapPagePage
Exercise 4

  • src/java/simpledb/storage/HeapPageId.java
  • src/java/simpledb/storage/RecordId.java
  • src/java/simpledb/storage/HeapPage.java

硬盘中包含很多文件,其中有的文件就是我们的HeapFile,一个HeapFile中存储了我们这个数据库中的所有表。文件由硬盘中的许多页(Page)构成,在我们的实现中,每个Page存储一个Table,当Page被加载到内存中后它就是一个表的形式。而每个页又包含很多slot,一个slot里有一个tuple。

1.HeapPageId.java

HeapPage对象的唯一标识符。

2.RecordID

RecordId是对特定表的特定页上的特定元组的引用。

3.HeapPage.java

HeapPage中的核心是数据是怎样HeapPage中组织的,这里主要是由header和tuples两个部分组成。其中,一条tuple在HeapPage中表示为一个slot,而header以bitmap的形式来表示第i个slot是否被占用,最低位表示第一个slot是否被占用。由于header是一个byte类型数据,所以最后一个字节并不一定都表示一个slot,也可能无意义:

public class HeapPage implements Page {

    final HeapPageId pid;
    // 每个数据页存储的是同一张表格的数据,所有只需要使用TupleDesc来描述即可
    final TupleDesc td;
    // 数据页的头部,使用bitmap来保存各个slot的占用情况,从最低位开始数
    final byte header[];
    // 具体的记录,即数据
    final Tuple tuples[];
    // 一共有多少个slot,即该数据页一共有多少条记录
    final int numSlots;

    byte[] oldData;
}
4.总结

HeapPage中各个字段的存储结构和分布,有个BitMap变量来表示各个位置有没有被使用。HeapPage中tuple数组来存储真正的一行一行数据,除此之外还有一个heapPageId和tupleDesc字段。

一个HeapPage能存多少行Tuple,取决于他要保存的一个个元组有多长且都是什么元素,元组数量的计算:floor((BufferPool.getPageSize()*8) / (tuple size * 8 + 1))。 以byte为单位的header数组的长度是:ceiling(no. tuple slots / 8) 。最后要注意实验中位图标记slot是否被使用的位运算是从右往左进行的,如0000—>0011这样。

Exercise5 HeapFile

To read a page from disk, you will first need to calculate the correct offset in the file. Hint: you will need random access to the file in order to read and write pages at arbitrary offsets. You should not call BufferPool methods when reading a page from disk.

You will also need to implement the HeapFile.iterator() method, which should iterate through through the tuples of each page in the HeapFile. The iterator must use the BufferPool.getPage() method to access pages in the HeapFile. This method loads the page into the buffer pool and will eventually be used (in a later lab) to implement locking-based concurrency control and recovery. Do not load the entire table into memory on the open() call – this will cause an out of memory error for very large tables.

1.HeapFile

HeapFile是DbFile的一个实现,它以无特殊顺序存储元组集合。 元组存储在页面上,每个页面都有固定的大小,文件只是这些页面的集合。 HeapFile与HeapPage紧密合作。 HeapPages的格式在HeapPage构造函数中描述。

2.总结

‎要从磁盘读取页面,首先需要计算文件中的正确偏移量。提示:您需要随机访问该文件,以便以任意偏移量读取和写入页面。从磁盘读取页时,不应调用 BufferPool 方法。‎一个HeapFile就是一张表/一个文件。HeapFile.readPage方法是核心,该方法只会被BufferPool调用,方法根据传入的pageId从磁盘中读取一个page。 还有就是HeapFile的迭代挺难,HeapFileIterator相当于是对整个表中所有的元组进行了迭代操作,需要复写接口的next, hasNext, open三个方法,基本思路是对File中的每个Page进行元组迭代,需要自己维护currentPage和游标。

Exercise 6 Operators

Operators are responsible for the actual execution of the query plan. They implement the operations of the relational algebra. In SimpleDB, operators are iterator based; each operator implements the interface.DbIterator

Operators are connected together into a plan by passing lower-level operators into the constructors of higher-level operators, i.e., by ‘chaining them together.’ Special access method operators at the leaves of the plan are responsible for reading data from the disk (and hence do not have any operators below them).

At the top of the plan, the program interacting with SimpleDB simply calls on the root operator; this operator then calls on its children, and so on, until these leaf operators are called. They fetch tuples from disk and pass them up the tree (as return arguments to ); tuples propagate up the plan in this way until they are output at the root or combined or rejected by another operator in the plan.getNextgetNextgetNext

数据库Operators(操作符)负责查询语句的实际执行。在SimpleDB中,Operators是基于迭代器实现的,每种iterator实现了一个DbIterator接口。SeqScan则为顺序扫描的功能,提供表内数据的迭代。

1.SeqScan.java

SeqScan是一个顺序扫描访问方法的实现,它读取表的每个元组,没有特定的顺序(例如,当它们被放置在磁盘上时)。

2.总结

全表顺序扫描的实现,相当于select * from table.

实验总结

lab1实现的都是些基础的整体架构,一开始看到怼过来的代码很蒙圈,梳理了下所有类的概念才慢慢明白。

标签:SimpleDb,BufferPool,tuple,元组,lab1,tid,table,MIT6.830,Page
来源: https://blog.csdn.net/fighting_yifeng/article/details/122814499