bustub-2
Ludwig Huang2. Access Methods
CMU 15-445 Project Review: Access Methods
In this series, I will show you how to build a disk-oriented DBMS (Database Management System) roughly. This article is about Access Methods, contains: Index, Index Page Layout, Extendible Hash Table.
This article mainly describes: How to support the DBMS's execution engine to read/write data from pages.
N. Logging & Recovery ^ Up (high level) 4. Concurrency Control | N. Query Planning | 3. Operator Execution | 2. Access Methods | <- Today 1. Buffer Pool Manager | 0. Disk Manager | Bottom (low level)
Index
DBMSs need some data structures for: Internal Meta-data, Core Data Storage, Temporary Data Structures, Table Indexes. In this article, we only concern about table indexes.
There are two main types of indexes: Hash Index, Ordered Index (B-Tree). Ordered index is sufficient in almost everything: range scan, comparation, point-finding. Hash index is sufficient in point-finding, bad in others.
Table index is much smaller than the entire table, and the content must be synchronized to the table. Indexes are critical for efficient processing of queries in databases. Without indexes, every query would end up reading the whole content of tables it needs. In general, indexes will store {key,rid}s.
This article only covers hash index. Hash index has a hash table container to deal with point-finding, which maintains directory pages and bucket pages. Our hash index only supports point-finding and scan key and all stuff is implemented in container.
Index Page Layout
In extendible hash table, there are two types of index page: directory page and bucket page.
directory page:
Record page id for each bucket. To locate a bucket, use the LSBs of hash value on a key; then, get the bucket's page id via one-to-one array.
Each directory page maintains a global depth (GD) and each bucket's local depth (LD). When we need a tuple, first hash it on its key, then use the LSBs to locate the bucket, search the tuple on the bucket linearly.
# directory page: ----------------------------------------------------------------------- | LSN(4) | PageId(4) | GD(4) | LDs(512) | BktPageIds(2048) | Free(1524) -----------------------------------------------------------------------
bucket page:
Store K-V{key, rid} pairs; Search linearly by hash value.
Each bucket page maintains an array of K-V pairs. For convenience, it also maintains bitmap for each K-V pairs.
# bucket page: -------------------------------------------------------------------- | Bitmap | KEY(1)+VALUE(1) | KEY(2)+VALUE(2) | ... | KEY(n)+VALUE(n) --------------------------------------------------------------------
Extendible Hash Table
For hash table, there are two critical design decisions:
- Hash Function: Low hash collision, high speed.
In bustub, we use third-party MurmurHash. - Hashing Scheme: Handle collisions, quick search.
In bustub, we use a dynamic hashing scheme called extendible hash table
There are three operations on extendible hash table:
GetValue
: Get the values by a specific key
Lock Scheme: RLock on bucket page; RLock on table (directory page).
- Fetch directory page
dir_page
- Fetch bucket page
bkt_page
by hash(key) - Search linearly to find the tuple by hash(key)
Insert
: Insert K-V pair into hash table
Lock Scheme: WLock on bucket page; RLock on table if no splitting, WLock otherwise.
Check whether the bucket is full: if not, just insert it. Otherwise, follow the steps below:
- Fetch
bkt_page
by hash(key) - Before splitting, increment local depth
- Check if hash table has to grow directory: if is(LD > GD), increment GD
- Initialize a split image bucket page
img_page
- Re-hash the existing k/v pairs (in
bkt_page
) intoimg_page
andbkt_page
- Re-organize bucket page pointers in directory page: the prev half points to
bkt_page
, the next half points toimg_page
- Insert the k/v until success or fail
Remove
: Remove K-V pair from the hash table
Lock Scheme: WLock on bucket page; RLock on table if no merging, WLock otherwise.
Remove k/v, check whether the bucket is empty: if is, return. Otherwise, follow the steps below:
- Check three primitives, determine to merge or not
- Delete empty bucket page
bkt_page
- Prev
bkt_page
points to image bucket pageimg_page
- Decrement local depth
- Re-organize all buckets in directory page
- Shrink if needed
For more details, refer to extendible-hashing.
Summary
In summary, hash index is responsible for fast data retrieval without having to search through every record in a database table. We implement hash table in extendible hash table scheme, using MurmurHash as the hash function.
Published by Tech Blog - Huang Blog.