Pebble
Coverage
Production Ready
Pebble was introduced as an alternative storage engine to RocksDB in CockroachDB v20.1 (released May 2020) and was used in production successfully at that time. Pebble was made the default storage engine in CockroachDB v20.2 (released Nov 2020). Pebble is being used in production by users of CockroachDB at scale and is considered stable and production ready.
Advantages
Pebble offers several improvements over RocksDB:
- Faster reverse iteration via backwards links in the memtable’s skiplist.
- Faster commit pipeline that achieves better concurrency.
- Seamless merged iteration of indexed batches. The mutations in the batch conceptually occupy another memtable level.
- L0 sublevels and flush splitting for concurrent compactions out of L0 and reduced read-amplification during heavy write load.
- Faster LSM edits in LSMs with large numbers of sstables through use of a copy-on-write B-tree to hold file metadata.
- Delete-only compactions that drop whole sstables that fall within the bounds of a range deletion.
- Block-property collectors and filters that enable iterators to skip tables, index blocks and data blocks that are irrelevant, according to user-defined properties over key-value pairs.
- Range keys API, allowing KV pairs defined over a range of keyspace with user-defined semantics and interleaved during iteration.
- Smaller, more approachable code base.
See the Pebble vs RocksDB: Implementation Differences doc for more details on implementation differences.
Pedigree
Pebble is based on the incomplete Go version of LevelDB:
https://github.com/golang/leveldb
The Go version of LevelDB is based on the C++ original:
https://github.com/google/leveldb
Optimizations and inspiration were drawn from RocksDB:
https://github.com/facebook/rocksdb
Getting Started
Example Code
package main
import (
"fmt"
"log"
"github.com/cockroachdb/pebble"
)
func main() {
db, err := pebble.Open("demo", &pebble.Options{})
if err != nil {
log.Fatal(err)
}
key := []byte("hello")
if err := db.Set(key, []byte("world"), pebble.Sync); err != nil {
log.Fatal(err)
}
value, closer, err := db.Get(key)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s %s\n", key, value)
if err := closer.Close(); err != nil {
log.Fatal(err)
}
if err := db.Close(); err != nil {
log.Fatal(err)
}
}