Home

Awesome

ObjectiveRocks

ObjectiveRocks is an Objective-C wrapper of Facebook's RocksDB - A Persistent Key-Value Store for Flash and RAM Storage.

Build Status Carthage Compatible License MIT

<!-- [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/ObjectiveRocks.svg?style=flat)](https://cocoapods.org/pods/ObjectiveRocks) [![CocoaDocs](https://img.shields.io/cocoapods/metrics/doc-percent/ObjectiveRocks.svg?style=flat)](http://cocoadocs.org/docsets/ObjectiveRocks) [![Platform](https://img.shields.io/cocoapods/p/ObjectiveRocks.svg?style=flat)](http://cocoadocs.org/docsets/ObjectiveRocks) -->

Current RocksDB Version: v6.2.4


Quick Overview

RocksDB is a key-value store, where the keys and values are arbitrarily-sized byte streams. The keys are ordered within the key value store according to a specified comparator function. RocksDB supports atomic reads and writes, snapshots, iteration and features many configuration options.

ObjectiveRocks provides an easy interface to RocksDB and an Objective-C friendly API that abstracts away the underlying C++ implementation, so you don't have to deal with it. While there is no need to learn the details about RocksDB to use this wrapper, a basic understanding of the internals is recommended and would explain the design decisions behind the, somewhat opinionated, API.

If you are interested in the internals of RocksDB, please refer to the RocksDB Wiki.

Swift

ObjectiveRocks has a pure Objective-C interface and can be used in Swift projects. Additionally, all ObjectiveRocks tests are also ported to Swift. You can check the Tests targets and source code which also contain bridging headers for OSX and iOS ObjectiveRocks implementations.

The Minimum You Need to Know

RocksDB Lite

ObjectiveRocks incldues two targets, for iOS and macOS. The iOS target builds the RocksDB Lite version, which doesn't include the complete feature set.

These features are only available in macOS:

Installation

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

If you don't have Carthage yet, you can install it with Homebrew using the following command:

$ brew update
$ brew install carthage

To add ObjectiveRocks as a dependency into your project using Carthage just add the following line in your Cartfile:

github "iabudiab/ObjectiveRocks"

Then run the following command to build the framework and drag the built ObjectiveRocks.framework into your Xcode project.

$ carthage update

Manually

1- Add ObjectiveRocks as git submodule

$ git submodule add https://github.com/iabudiab/ObjectiveRocks.git

2- Open the ObjectiveRocks folder and drag'n'drop the ObjectiveRocks.xcodeproj into the Project Navigator in Xcode to add it as a sub-project.

3- In the General panel of your target add ObjectiveRocks.framework under the Embedded Binaries

Notice that ObjectiveRocks depends on RocksDB and includes it as a Git submodule.

Usage

The README will use the NSString notation in place of NSData keys and values for brevity!

Open & close a DB instance

To open a database you have to specify its location:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db"];
...
[db close];

RocksDB features many configuration settings, that can be specified when opening the database. ObjectiveRocks offers a blocks-based initializer for this purpose. The minimum configuration that you'll need is createIfMissing in order to create a new database if it doesn't already exist:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.createIfMissing = YES;
}];

The configuration guide, lists all currently available options along with their description.

A more production ready setup could look like this:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.createIfMissing = YES;

	options.maxOpenFiles = 50000;

	options.tableFacotry = [RocksDBTableFactory blockBasedTableFactoryWithOptions:^(RocksDBBlockBasedTableOptions *options) {
		options.filterPolicy = [RocksDBFilterPolicy bloomFilterPolicyWithBitsPerKey:10];
		options.blockCache = [RocksDBCache LRUCacheWithCapacity:1024 * 1024 * 1024];
		options.blockSize = 64 * 1024;
	}];

	options.writeBufferSize = 64 * 1024 * 1024;
	options.maxWriteBufferNumber = 7;
	options.targetFileSizeBase = 64 * 1024 * 1024;
	options.numLevels = 7;

	options.maxLogFileSize = 50 * 1024 * 1024;
	options.keepLogFileNum = 30;
}];

Basic Operations

The database provides three basic operations, Put, Get, and Delete to store/query data. Keys and values in RocksDB are arbitrary byte arrays:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.createIfMissing = YES;
}];

NSData *data = [@"World" dataUsingEncoding:NSUTF8StringEncoding]
NSData *key = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding]

[db storeData:data forKey:key];
NSData *get = [db getDataForKey:key];
[db deleteDataForKey:key];

Read & Write Errors

Database operations can be passed a NSError reference to check for any errors that have occurred:

NSError *error = nil;

[db setObject:object forKey:key error:&error];
NSMutableDictionary *dictionary = [db dataForKey:@"Hello" error:&error];
[db deleteDataForKey:@"Hello" error:&error];

Read & Write Options

Each single read or write operation can be tuned via specific options:

[db setObject:anObject forKey:aKey writeOptions:^(RocksDBWriteOptions *writeOptions) {
	writeOptions.syncWrites = YES;
	writeOptions.disableWriteAheadLog = YES;
	writeOptions.timeoutHint = 5;
	writeOptions.ignoreMissingColumnFamilies = NO;
}];

[db dataForKey:aKey readOptions:^(RocksDBReadOptions *readOptions) {
	readOptions.verifyChecksums = YES;
	readOptions.fillCache = NO;
}];

Default options can also be set on a RocksDB or RocksDBColumnFamily instance:

[db setDefaultReadOptions:^(RocksDBReadOptions *readOptions) {
	readOptions.fillCache = YES;
	readOptions.verifyChecksums = YES;
} andWriteOptions:^(RocksDBWriteOptions *writeOptions) {
	writeOptions.syncWrites = YES;
	writeOptions.timeoutHint = 5;
}];

You can read about the read and write options in the configuration guide

Iteration

Iteration is provided via the RocksDBIterator class.

You can either iterate manually:

RocksDB *db = ...;
RocksDBColumnFamily *stuffColumnFamily = .../

RocksDBIterator *iterator = [db iterator];
RocksDBIterator *cfIterator = [stuffColumnFamily iterator];

// Alternatively, you can get an iterator with specific read options
iterator = [db iteratorWithReadOptions:^(RocksDBReadOptions *readOptions) {
	// Read options here
}];

for ([iterator seekToKey:@"start"]; [iterator isValid]; [iterator next]) {
	NSLog(@"%@: %@", [iterator key], [iterator value]);
	// Iterates all keys starting from key "start" 
}

or use one of the provided enumeration-blocks:

[db setData:@"Value 1" forKey:@"A"];
[db setData:@"Value 2" forKey:@"B"];
[db setData:@"Value 3" forKey:@"C"];
[db setData:@"Value 3" forKey:@"D"];

RocksDBIterator *iterator = [db iterator];

/* Keys Enumeration */
[db enumerateKeysUsingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@", key);
	// A, B, C, D
}];

// reverse enumeration
[db enumerateKeysInReverse:YES usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@", key);
	// D, C, B, A
}];

// Enumeration in a given key-range [start, end)
RocksDBIteratorKeyRange range = RocksDBMakeKeyRange(@"A", @"C");

[db enumerateKeysInRange:range reverse:NO usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@", key, [db dataForKey:key]);
	// B, C
}];

/* Key-Value Enumeration */
[db enumerateKeysAndValuesUsingBlock:^(NSData *key, NSData *value BOOL *stop) {
	NSLog(@"%@:%@", key, value);
	// A:1, B:2, C:3, D:4
}];

[db enumerateKeysAndValuesInReverse:YES usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@: %@", key, [db dataForKey:key]);
	// D:4, C:3, B:2, A:1
}];

// Enumeration in a given key-range [start, end)
RocksDBIteratorKeyRange range = RocksDBMakeKeyRange(@"A", @"C");

[db enumerateKeysAndValuesInRange:range reverse:YES usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@:%@", key, [db dataForKey:key]);
	// B:2, C:3
}];

Prefix-Seek Iteration

RocksDBIterator supports iterating inside a key-prefix by providing a RocksDBPrefixExtractor. One such extractor is built-in and it extracts a fixed-length prefix for each key:

RocksDB *db = [RocksDB databaseAtPath:_path andDBOptions:^(RocksDBOptions *options) {
	options.createIfMissing = YES;
	options.prefixExtractor = [RocksDBPrefixExtractor prefixExtractorWithType:RocksDBPrefixFixedLength length:2];
}];

[db setData:@"a" forKey:@"10.1"];
[db setData:@"b" forKey:@"10.2"];
[db setData:@"b" forKey:@"10.3"];
[db setData:@"c" forKey:@"11.1"];
[db setData:@"d" forKey:@"11.2"];
[db setData:@"d" forKey:@"11.3"];

RocksDBIterator *iterator = [db iterator];

// Enumeration starts with the key that is Greater-Than-Or-Equal to a key
// with the given "prefix" parameter
[iterator enumerateKeysWithPrefix:@"10" usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@", key);
	// 10.1, 10.2, 10.3
}];

// .. so in this case the enumeration starts at key "10.2", even if "10.1" 
// has the same prefix
[iterator enumerateKeysWithPrefix:@"10.2" usingBlock:^(NSData *key, BOOL *stop) {
	NSLog(@"%@", key);
	// 10.2, 10.3
}];

You can also define your own Prefix Extractor:

RocksDBPrefixExtractor *extractor = [[RocksDBPrefixExtractor alloc] initWithName:@"custom_prefix"
	transformBlock:^id (NSData *key) {
		// Apply your key transformation to extract the prefix part
		id prefix = extractPrefixFromKey(key);
		return prefix;
	}
	prefixCandidateBlock:^BOOL (NSData *key) {
		// You can filter out keys that are not viable candidates for
		// your custom prefix format, e.g. key length is smaller than
		// the target prefix length
		BOOL isCandidate = canExtractPrefixFromKey(key);
		return isCandidate;
	}
	validPrefixBlock:^BOOL (NSData *prefix) {
		// After a prefix is extracted you can perform extra
		// checks here to verify that the prefix is valid
		BOOL isValid = isExtractedPrefixValid(prefix);
		return isValid;
	}
];

Column Families

Once you have a RocksDB instance you can create and drop column families on the fly:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:...];

RocksDBColumnFamily *columnFamily = [db createColumnFamilyWithName:@"new_column_family" andOptions:^(RocksDBColumnFamilyOptions *options) {
	// Options for the new column family
};
// Do stuff with columnFamily and close it when you're done
[columnFamily close];

// To drop it
[columnFamily drop];

Notice that the RocksDBColumnFamily is a subclass of RocksDB

If the database already contains Column Families other than the default, then you need to specify all Column Families that currently exist in the database when opening it, including the default one. You specify the Column Families using a RocksDBColumnFamiliesDescriptor object:

RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new];

[descriptor addColumnFamilyWithName:@"default" andOptions:^(RocksDBColumnFamilyOptions *options) {
	// Options for the default column family
}];
[descriptor addColumnFamilyWithName:@"stuff_column_family" andOptions:^(RocksDBColumnFamilyOptions *options) {
	// Options for the stuff_column_family
}];

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) {
	// Database options here
}];

NSArray *columnFamilies = db.columnFamilies;
RocksDBColumnFamily *defaultColumnFamily = columnFamilies[0];
RocksDBColumnFamily *stuffColumnFamily = columnFamilies[1];
// At this point you can either use the db instance or 
// the defaultColumnFamily instance to access the default column family

Atomic Updates

You can atomically apply a set of updates to the database using a WriteBatch. There are two ways to use a WriteBatch:

[db setData:@"Value 1" forKey:@"Key 1"];

[db performWriteBatch:^(RocksDBWriteBatch *batch, RocksDBWriteOptions *writeOptions) {
	[batch setData:@"Value 2" forKey:@"Key 2"];
	[batch setData:@"Value 3" forKey:@"Key 3"];
	[batch deleteDataForKey:@"Key 1"];
}];
[db setData:@"Value 1" forKey:@"Key 1"];

RocksDBWriteBatch *batch = [db writeBatch];
[batch setData:@"Value 2" forKey:@"Key 2"];
[batch setData:@"Value 3" forKey:@"Key 3"];
[batch deleteDataForKey:@"Key 1"];
...
[db applyWriteBatch:batch withWriteOptions:^(RocksDBWriteOptions *writeOptions) {
	// Write options here
}];

The Write Batch object operates per default on the Column Family associated with the DB instance, which was used to create it. However, you can also specify the Column Family, in order to achieve an atomic write across multiple Column Families. In this case it doesn't matter on which instance you apply the batch:

RocksDB *db = ...;
RocksDBColumnFamily *stuffColumnFamily = .../

// Write Batch for default column family
RocksDBWriteBatch *batch = [db writeBatch];

// Write Batch for stuffColumnFamily
RocksDBWriteBatch *cfBatch = [stuffColumnFamily writeBatch];

[batch setData:@"Value 1" forKey:@"Key 1"];
[batch setData:@"Value 2" forKey:@"Key 2" inColumnFamily:stuffColumnFamily];

// You can apply the Write Batch object either on the DB instance
// or the stuffColumnFamily instance.
// The following two calls have the same effect:
/**
	[db applyWriteBatch:batch withWriteOptions:^(RocksDBWriteOptions *writeOptions) {
		// Write options here
	}];
	[stuffColumnFamily applyWriteBatch:batch withWriteOptions:^(RocksDBWriteOptions *writeOptions) {
		// Write options here
	}];
*/

Snapshot

A Snapshot provides consistent read-only view over the state of the key-value store. Do not forget to close the snapshot when it's no longer needed:

[db setData:@"Value 1" forKey:@"A"];

RocksDBSnapshot *snapshot = [db snapshot];
// Alternatively, you can get a snapshot with specific read options
snapshot = [db snapshotWithReadOptions:^(RocksDBReadOptions *readOptions) {
	// Read options here
}];

[db deleteDataForKey:@"A"];
[db setData:@"Value 2" forKey:@"B"];

NSString *value1 = [snapshot dataForKey:@"A"];
// value1 == @"Value 1"
NSString *value2 = [snapshot dataForKey:@"B"];
// value2 == nil
...
[snapshot close];

Checkpoint

A checkpoint is an openable Snapshot of a database at a point in time:

[db setData:@"Value 1" forKey:@"A"];
[db setData:@"Value 2" forKey:@"B"];

RocksDBCheckpoint *checkpoint = [[RocksDBCheckpoint alloc] initWithDatabase:db];
NSError *error = nil;
[checkpoint createCheckpointAtPath:@"path/to/checkpoint" error:&error];

RocksDB *db2 = [RocksDB databaseAtPath:@"path/to/checkpoint"];
...
[db close];
[db2 close];

Keys Comparator

The keys are ordered within the key-value store according to a specified comparator function. The default ordering function for keys orders the bytes lexicographically.

This behavior can be changed by supplying a custom Comparator when opening a database using the RocksDBComparator.

Say you have NSString keys and you want them to be ordered using a case-insensitive, localized, comparison:

RocksDBComparator *localizedKeys = [[RocksDBComparator alloc] initWithName:@"LocalizedKeys" andBlock:^int (NSData *key1, NSData *key2) {
	return [key1 localizedCaseInsensitiveCompare:key2];
];
	
RocksDB *db = [RocksDB databaseAtPath:_path andDBOptions:^(RocksDBOptions *options) {
	options.comparator = localizedKeys;
}];

The comparator's name is attached to the database when it is created, and is checked on every subsequent database open. If the name changes, the open call will fail. Therefore, change the name if new key format and comparison function are incompatible with existing database, and it is ok to discard the contents of the existing database.

Built-In Comparators

ObjectiveRocks features some built-in comparators, which can be used like this:

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.comparator = [RocksDBComparator comaparatorWithType:RocksDBComparatorNumberAscending];
}];

Merge Operator

A Merge operators is an atomic Read-Modify-Write operation in RocksDB. For a detailed description visit the Merge Operator wiki page in the RocksDB project.

Analogous to the comparator a database created using one merge operator cannot be opened using another.

Associative Merge Operator

You can use this Merge Operator when you have associative data:

For example we can use a merge operator to append entries to an existing array, instead of reading it completely, updating it and writing it back:

RocksDBMergeOperator *arrayAppend = [RocksDBMergeOperator operatorWithName:@"ArrayAppend" andBlock:^id (NSData *key, NSData *existingValue, NSData *mergeValue) {
	if (existingValue == nil) {
		return mergeValue;
	} else {
		[existingValue addObjectsFromArray:mergeValue];
		return existingValue;
	}
}];

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.mergeOperator = arrayAppend;
}];

NSMutableArray *letters = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

[db setData:letters forKey:@"Key"];
[db mergeData:@[@"C", @"D"] forKey:@"Key"];
[db mergeData:@[@"E"] forKey:@"Key"];

NSMutableArray *merged = [db dataForKey:@"Key"];
// merged = @[@"A", @"B", @"C", @"D", @"E"];

Generic Merge Operator

If either of the two associativity constraints do not hold, then use the Generic Merge Operator.

The Generic Merge Operator has two methods, PartialMerge, FullMerge:

ObjectiveRocks has a new mergeOperation method for use with a generic Merge Operator. This contrived example shows how a generic merge operator can be used with client-defined merge operations:

RocksDBMergeOperator *mergeOp = [RocksDBMergeOperator operatorWithName:@"operator"
	partialMergeBlock:^id(NSData *key, NSData *leftOperand, NSData *rightOperand) {
		NSString *left = [leftOperand componentsSeparatedByString:@":"][0];
		NSString *right = [rightOperand componentsSeparatedByString:@":"][0];
		if ([left isEqualToString:right]) {
			return rightOperand;
		}
		return nil;
	} fullMergeBlock:^id(id key, id *existing, NSArray *operands) {
		for (NSString *operand in operands) {
			NSArray *components = [operand componentsSeparatedByString:@":"];
			NSString *action = components[1];
			if	([action isEqualToString:@"DELETE"]) {
				[existing removeObjectForKey:components[0]];
			} else {
				existing[comp[0]] = components[2];
			}
		}
		return existing;
	}
];
	
RocksDB *db = [RocksDB databaseAtPath:_path andDBOptions:^(RocksDBOptions *options) {
	options.createIfMissing = YES;
	options.mergeOperator = mergeOp;
}];

NSDictionary *object = @{@"Key 1" : @"Value 1",
						 @"Key 2" : @"Value 2",
						 @"Key 3" : @"Value 3"};

[db setObject:object forKey:@"Dict Key"];

[db mergeData:@"Key 1:UPDATE:Value X" forKey:@"Dict Key"];
[db mergeData:@"Key 4:INSERT:Value 4" forKey:@"Dict Key"];
[db mergeData:@"Key 2:DELETE" forKey:@"Dict Key"];
[db mergeData:@"Key 1:UPDATE:Value 1 New" forKey:@"Dict Key"];

id result = [db dataForKey:@"Dict Key"];
/**
result = @{@"Key 1" : @"Value 1 New",
		   @"Key 3" : @"Value 3",
		   @"Key 4" : @"Value 4"};
*/

Env & Thread Status

The RocksDBEnv allows for modifying the thread pool for backgrond jobs. RocksDB uses this thread pool for compactions and memtable flushes.

RocksDBEnv *dbEnv = [RocksDBEnv envWithLowPriorityThreadCount:12 andHighPriorityThreadCount:4];
RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.env = dbEnv;
}];

// To get a list of all threads
NSArray *threads = dbEnv.threadList;

// "threads" array contains objects of type RocksDBThreadStatus
RocksDBThreadStatus *status = threads[0];

Backup & Restore

To backup a database use the RocksDBBackupEngine:

RocksDB *db = ...

RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:@"path/to/backup"];
NSError *error = nil;
[backupEngine createBackupForDatabase:db error:&error];
...
[backupEngine close];

To restore a database backup:

RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:@"path/to/backup"];
backupEngine restoreBackupToDestinationPath:@"path/to/db" error:nil];
backupEngine close];

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db"];
...
[db2 close];

Backups are incremental and only the new data will be copied to backup directory, so you can:

RocksDB *db = ...

RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:@"path/to/backup"];

[db setData:@"Value 1" forKey:@"A"];
[backupEngine createBackupForDatabase:db error:nil];

[db setData:@"Value 2" forKey:@"B"];
[backupEngine createBackupForDatabase:db error:nil];

[db setData:@"Value 3" forKey:@"C"];
[backupEngine createBackupForDatabase:db error:nil];

// An array containing RocksDBBackupInfo objects
NSArray *backupInfo = backupEngine.backupInfo;

// Restore second backup
[backupEngine restoreBackupWithId:2 toDestinationPath:@"path/to/db" error:nil];

// Delete first backup
[backupEngine deleteBackupWithId:1 error:nil];

// Purge all except the last two
[backupEngine purgeOldBackupsKeepingLast:2 error:nil];

Statistics

You can collect those statistics by creating and setting the RocksDBStatistics object in the database options:

RocksDBStatistics *dbStatistics = [RocksDBStatistics new];

RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
	options.statistics = dbStatistics;
}];
...

[dbStatistics countForTicker:RocksDBTickerBytesRead];
RocksDBStatisticsHistogram *dbGetHistogram = [dbStatistics histogramDataForType:RocksDBHistogramDBGet];

Available Tickers and Histograms are defined in RocksDBStatistics.h

Properties

The database exports some properties about its state via properties on a per column family level. Available properties are defined in RocksDBProperties.h

RocksDB *db = ...

NSString *dbStats = [db valueForProperty:RocksDBPropertyDBStats];
uint64_t sizeActiveMemTable = [db valueForIntProperty:RocksDBIntPropertyCurSizeActiveMemTable];

Configuration <a name="configuration"></a>

Currently only a subset of all RocksDB's available options are wrapped/provided.

Further options will be added in later versions (mostly when I get the time to experiment with them and figure out what they do)

ObjectiveRocks DB Options

OptionDescriptionDefault Value
createIfMissingThe database will be created if it is missingfalse
createMissingColumnFamiliesMissing column families will be automatically createdfalse
errorIfExistsAn error is raised if the database already existsfalse
paranoidChecksRocksDB will aggressively check consistency of the datatrue
infoLogLevelLog levelINFO
maxOpenFilesNumber of open files that can be used by the DB5000
maxWriteAheadLogSizeMax size of write-ahead logs before force-flushing0 (= dynamically chosen)
statisticsIf non-nil, metrics about database operations will be collectednil
disableDataSyncContents of manifest and data files wont be synced to stable storagefalse
useFSyncEvery store to stable storage will issue a fsyncfalse
maxLogFileSizeMax size of the info log file, will rotate when exceeded0 (= all logs written to one file)
logFileTimeToRollTime for the info log file to roll (in seconds)0 (disabled)
keepLogFileNumMaximal info log files to be kept1000
bytesPerSyncIncrementally sync files to disk while they are being written0 (disabled)

ObjectiveRocks Column Family Options

OptionDescriptionDefault Value
comparatorUsed to define the order of keys in the tableLexicographic byte-wise ordering
mergeOperatorMust be provided for merge operationsnil
writeBufferSizeAmount of data to build up in memory before writing to disk4 * 1048576 (4MB)
maxWriteBufferNumberThe maximum number of write buffers that are built up in memory2
minWriteBufferNumberToMergeThe minimum number of write buffers that will be merged together before writing to storage1
compressionTypeCompress blocks using the specified compression algorithmSnappy Compression
prefixExtractorIf non-nil, the specified function to determine the prefixes for keys will be usednil
numLevelsNumber of levels for the DB7
level0FileNumCompactionTriggerCompress blocks using the specified compression algorithm4
level0SlowdownWritesTriggerSoft limit on number of level-0 files20
level0StopWritesTriggerMaximum number of level-0 files24
targetFileSizeBaseTarget file size for compaction2 * 1048576 (2MB)
targetFileSizeMultiplierMultiplier for sizes of files in different levels1 (files in different levels will have similar size)
maxBytesForLevelBaseControl maximum total data size for a level10 * 1048576 (10MB)
maxBytesForLevelMultiplierMultiplier for file size per level10
expandedCompactionFactorMaximum number of bytes in all compacted files25
sourceCompactionFactorMaximum number of bytes in all source files to be compacted in a single compaction run1
maxGrandparentOverlapFactorControl maximum bytes of overlaps in grandparent (i.e., level+2)10
softRateLimitPuts are delayed 0-1 ms when any level has a compaction score that exceeds this limit0 (disabled)
hardRateLimitPuts are delayed 1ms at a time when any level has a compaction score that exceeds this limit0 (disabled)
arenaBlockSizeSize of one block in arena memory allocation0
disableAutoCompactionsDisable automatic compactionsfalse
purgeRedundantKvsWhileFlushPurge duplicate/deleted keys when a memtable is flushed to storagetrue
verifyChecksumsInCompactionIf true, compaction will verify checksum on every read that happens as part of compactiontrue
filterDeletesUse KeyMayExist API to filter deletes when this is truefalse
maxSequentialSkipInIterationsAn iteration->Next() sequentially skips over keys with the same user-key unless this option is set8
memTableRepFactoryA factory that provides MemTableRep objectsnil. Internallty RocksDB will use a factory that provides a skip-list-based implementation of MemTableRep
tableFacotryA factory that provides TableFactory objectsnil. Internallty RocksDB will use a block-based table factory that provides a default implementation of TableBuilder and TableReader with default BlockBasedTableOptions
memtablePrefixBloomBitsIf prefixExtractor is set and bloom_bits is not 0, create prefix bloom for memtable0
memtablePrefixBloomProbesNumber of hash probes per key6
memtablePrefixBloomHugePageTlbSizePage size for huge page TLB for bloom in memtable0
bloomLocalityControl locality of bloom filter probes to improve cache miss rate0
maxSuccessiveMergesMaximum number of successive merge operations on a key in the memtable0
minPartialMergeOperandsThe number of partial merge operands to accumulate before partial merge will be performed2

Read Options

OptionDescriptionDefault Value
verifyChecksumsData read will be verified against corresponding checksumstrue
fillCachewhether the read for this iteration be cached in memorytrue

Write Options

OptionDescriptionDefault Value
syncWritesWrites will be flushed from buffer before being considered completefalse
disableWriteAheadLogWrites will not first go to the write ahead logtrue
ignoreMissingColumnFamiliesIgnore writes to non-existing column familiesfalse

Table Formats

Memtable Formats

For more details visit the wiki Hash based memtable implementations