this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Rewrite table intro and trailer section

garrison ec5bb771 e79f1fea

+51 -28
+51 -28
rfds/001_xks_storage_engine.md
··· 163 163 164 164 ## Tables 165 165 166 - Tables are the on-disk "files" which store multiversion key/value pairs. 167 - In many LSM trees they are actual files, but here we use a single file and allocate blocks within that file ourselves. 166 + A table is a collection of multiversion key/value pairs stored in lexicographic order. 167 + Tables are large (32 MiB) and pairs are written compactly with no slack space or padding. 168 + 169 + A table consists of a number of subtables (or "subs") which are written consecutively to disk. 170 + The subs are followed first by a table index, which records the byte offset and key bounds of each sub, 171 + and then by a table trailer which records the metadata needed to read the table. 172 + 173 + At a high level, a lookup against the table can be performed as follows: 174 + 175 + 1. Read the last block of the table and load the table's metadata. 176 + 2. Binary search the table index to find the location of the sub containing the desired key. 177 + 3. Binary search the sub to find the key and its value. 178 + 179 + ### Table trailer 180 + 181 + The trailer is fully contained by the last block of the table and is aligned to the end of that block. 182 + 183 + The trailer consists of: 184 + 185 + - A list of block addresses (`index` and `checksum`) for the blocks in the table 186 + - The fixed-length metadata needed to decode the table 187 + 188 + #### Metadata 189 + 190 + The metadata is fixed-length and consists of the last 12 bytes of the last block of the table. 191 + 192 + ``` 193 + # Metadata: 194 + block_count (4 bytes) | index_slots_offset (4 bytes) | subtable_count (4 bytes) 195 + ``` 196 + 197 + The `block_count` records the number of block address entries which directly precede the metadata. 198 + Block address entries are fixed-length, so the count is enough to decode the addresses. 199 + 200 + The `index_slots_offset` records the byte offset of the table index's fixed-length slots. 201 + The `subtable_count` records the number of subtables in the table. 202 + Together, these can be used to locate the table index's slots and then binary search the index to find a sub. 203 + 204 + #### Block addresses 205 + 206 + The block addresses constitute a lookup table which can be used to find the block for a given byte offset in the table. 207 + There is no guarantee that these addresses are consecutive, as allocation will fragment over time. 168 208 169 - Tables are large (32 MiB) and store keys (with versions) in sorted order. 170 - The LSM is leveled, so within each level a table stores a disjoint portion of the keyspace. 209 + Each block address entry consists of 24 bytes: 171 210 172 - Each table is organized into subtables ("subs"). 173 - Subs are written sequentially, and then an index with the `start_key` for each sub is written to the end of the table. 174 - Along with the manifest, this forms a tree structure: manifest -> table index -> subtable -> key/value pair. 211 + ``` 212 + # Block address entry: 213 + index (8 bytes) | checksum (16 bytes) 214 + ``` 175 215 176 - Tables are written by a merge process, which accumulates pairs in sorted order and writes them out one sub at a time. 216 + By storing the list of block addresses entirely within the last block, 217 + we avoid having to build a linked list of blocks for the trailer. 218 + We can fit roughly 20,000 24-byte addresses within a 512 KiB block, 219 + so this approach limits us to a table size of around 10 GiB: *far* larger than we will ever need. 177 220 178 221 ### Subtables 179 222 ··· 246 289 The length of the `key` is stored implicitly as the difference between slot `offset`s. 247 290 248 291 The sub entries can be binary searched with an algorithm similar to that of the subs detailed above. 249 - 250 - ### Table Trailer 251 - 252 - At the end of the last block of the table, a metadata trailer is written. 253 - The table trailer consists of a list of addresses for the blocks of the table and then the top-level metadata values. 254 - If there is not enough room for this trailer in the last block, a new last block is allocated. 255 - 256 - ``` 257 - # Block entry: 258 - block_offset (8 bytes) | block_checksum (16 bytes) 259 - 260 - # Metadata: 261 - block_count (2 bytes) | sub_count (4 bytes) | index_offset (4 bytes) | index_size (4 bytes) 262 - ``` 263 - 264 - Each block entry consists of a block address as defined previously (`block_offset` and `block_checksum`). 265 - 266 - The `block_count` holds the number block entries (addresses). 267 - 268 - The `sub_count` is the number of subs, and the `index_offset` and `index_size` are the offset/size of the table index.