Learn how to scan and iterate through RocksDB data efficiently
Iterators provide an efficient way to scan through RocksDB data in sorted order. This guide covers basic iteration patterns, seeking strategies, and performance considerations.
Iterator* it = db->NewIterator(ReadOptions());// Seek to key >= "user:1000"it->Seek("user:1000");if (it->Valid()) { // Iterator is positioned at "user:1000" or the next key std::cout << "Found: " << it->key().ToString() << std::endl;} else { std::cout << "No keys >= user:1000" << std::endl;}delete it;
Iterator* it = db->NewIterator(ReadOptions());// Seek to key <= "user:1000"it->SeekForPrev("user:1000");if (it->Valid()) { // Iterator is positioned at "user:1000" or the previous key std::cout << "Found: " << it->key().ToString() << std::endl;}delete it;
Seek()
SeekForPrev()
SeekToFirst()
SeekToLast()
Positions iterator at the first key greater than or equal to target
Positions iterator at the first key less than or equal to target
Positions iterator at the first key in the database
Positions iterator at the last key in the database
Efficiently iterate over keys with a common prefix:
#include "rocksdb/slice_transform.h"using ROCKSDB_NAMESPACE::NewFixedPrefixTransform;// Configure prefix extractor (do this when opening the DB)Options options;options.prefix_extractor.reset(NewFixedPrefixTransform(4));// Later, iterate with prefixReadOptions read_options;read_options.prefix_same_as_start = true;Iterator* it = db->NewIterator(read_options);// Iterate over all keys with prefix "user"it->Seek("user");while (it->Valid()) { // Will only iterate over keys starting with "user" std::cout << it->key().ToString() << std::endl; it->Next();}delete it;
using ROCKSDB_NAMESPACE::Snapshot;// Create a snapshotconst Snapshot* snapshot = db->GetSnapshot();ReadOptions read_options;read_options.snapshot = snapshot;// Iterator reads from the snapshotIterator* it = db->NewIterator(read_options);for (it->SeekToFirst(); it->Valid(); it->Next()) { // Data is consistent with the snapshot std::cout << it->key().ToString() << std::endl;}assert(it->status().ok());delete it;// Release the snapshotdb->ReleaseSnapshot(snapshot);
Iterators created with a snapshot will read data as it existed when the snapshot was created, even if the data is subsequently modified or deleted.
ReadOptions read_options;read_options.fill_cache = false;Iterator* it = db->NewIterator(read_options);// Large scan won't evict useful data from cachedelete it;
ReadOptions read_options;read_options.tailing = true;Iterator* it = db->NewIterator(read_options);while (keep_monitoring) { it->SeekToLast(); if (it->Valid()) { // Process latest data ProcessKey(it->key(), it->value()); } // Wait before checking again std::this_thread::sleep_for(std::chrono::seconds(1));}delete it;
using ROCKSDB_NAMESPACE::ColumnFamilyHandle;std::vector<ColumnFamilyHandle*> column_families;std::vector<Iterator*> iterators;Status s = db->NewIterators(ReadOptions(), column_families, &iterators);assert(s.ok());for (size_t i = 0; i < iterators.size(); i++) { Iterator* it = iterators[i]; for (it->SeekToFirst(); it->Valid(); it->Next()) { // Process data from column family i } assert(it->status().ok()); delete it;}