Skip to main content

Overview

The Iterator class provides a way to sequentially scan through the contents of a RocksDB database. Iterators support both forward and backward iteration, seeking to specific keys, and accessing key-value pairs or wide-column entities.

Creating Iterators

Iterator* NewIterator(const ReadOptions& options)
Iterator* NewIterator(const ReadOptions& options, ColumnFamilyHandle* column_family)

// Helper functions
Iterator* NewEmptyIterator()
Iterator* NewErrorIterator(const Status& status)

Positioning Methods

SeekToFirst

void SeekToFirst()
Position at the first key in the source. The iterator is Valid() after this call iff the source is not empty.

SeekToLast

void SeekToLast()
Position at the last key in the source. The iterator is Valid() after this call iff the source is not empty.

Seek

void Seek(const Slice& target)
Position at the first key that is at or past target. The iterator is Valid() after this call iff the source contains an entry that comes at or past target.
target
const Slice&
Target key (does not contain timestamp).

SeekForPrev

void SeekForPrev(const Slice& target)
Position at the last key that is at or before target. The iterator is Valid() after this call iff the source contains an entry that comes at or before target.
target
const Slice&
Target key (does not contain timestamp).

Next

void Next()
Moves to the next entry. After this call, Valid() is true iff the iterator was not positioned at the last entry. REQUIRES: Valid()

Prev

void Prev()
Moves to the previous entry. After this call, Valid() is true iff the iterator was not positioned at the first entry. REQUIRES: Valid()

Access Methods

Valid

bool Valid() const
Returns true if the iterator is positioned at a valid key/value pair. Always returns false if !status().ok().

key

Slice key() const
Return the key for the current entry. The underlying storage is valid only until the next modification of the iterator. REQUIRES: Valid()

value

Slice value() const
Return the value for the current entry. If the entry is a plain key-value, return the value as-is. If it is a wide-column entity, return the value of the default anonymous column (see kDefaultWideColumnName) if any, or an empty value otherwise. REQUIRES: Valid()

columns

const WideColumns& columns() const
Return the wide columns for the current entry. If the entry is a wide-column entity, return it as-is. If it is a plain key-value, return it as an entity with a single anonymous column. REQUIRES: Valid()

timestamp

Slice timestamp() const
Return the timestamp for the current entry (when user-defined timestamps are enabled). REQUIRES: Valid()

status

Status status() const
If an error has occurred, return it. Otherwise return an ok status. Returns Status::Incomplete() if non-blocking I/O was requested and the operation cannot be satisfied without doing I/O.

Advanced Methods

PrepareValue

bool PrepareValue()
When ReadOptions::allow_unprepared_value is set, call this method before accessing the value to ensure it is prepared. Returns true on success. REQUIRES: Valid()

Refresh

Status Refresh()
Status Refresh(const Snapshot* snapshot)
Update the iterator to read from the latest DB state (or the specified snapshot). The iterator will be invalidated after the call. Call a Seek*() function to get the iterator back into a valid state.

GetProperty

Status GetProperty(std::string prop_name, std::string* prop)
Get iterator properties:
  • "rocksdb.iterator.is-key-pinned": Returns “1” if the key is pinned (valid as long as iterator is not deleted)
  • "rocksdb.iterator.is-value-pinned": Returns “1” if the value is pinned
  • "rocksdb.iterator.super-version-number": LSM version used by the iterator
  • "rocksdb.iterator.internal-key": Get the user-key portion of the internal key
  • "rocksdb.iterator.write-time": Get the estimated write time of the entry

Prepare (Experimental)

void Prepare(const MultiScanArgs& scan_opts)
Prepare the iterator to scan the ranges specified in scan_opts. This includes prefetching relevant blocks from disk.

Examples

ReadOptions options;
Iterator* it = db->NewIterator(options);

for (it->SeekToFirst(); it->Valid(); it->Next()) {
  std::cout << it->key().ToString() << ": "
            << it->value().ToString() << std::endl;
}

assert(it->status().ok());
delete it;

Iterator Lifecycle

  1. Create the iterator with DB::NewIterator()
  2. Position the iterator using Seek*() methods
  3. Navigate using Next() or Prev()
  4. Access data using key(), value(), or columns()
  5. Check validity with Valid() and errors with status()
  6. Delete the iterator when done

Error Handling

All Seek*() methods clear any previous error status. After seeking, status() indicates only errors that occurred during the seek, not past errors. Always check status() after iteration:
Iterator* it = db->NewIterator(ReadOptions());
for (it->SeekToFirst(); it->Valid(); it->Next()) {
  // Process entries
}

if (!it->status().ok()) {
  // Handle iteration error
}

delete it;

Thread Safety

Multiple threads can invoke const methods on an Iterator without external synchronization. However, if any thread may call a non-const method, all threads accessing the same Iterator must use external synchronization.

Performance Tips

  1. Set fill_cache=false for bulk scans to avoid polluting the block cache
  2. Use readahead_size for large sequential scans (e.g., 2MB+)
  3. Set iteration bounds (iterate_upper_bound) to enable optimizations
  4. Use prefix_same_as_start for prefix scans with prefix bloom filters
  5. Consider pin_data=true if repeatedly accessing iterator data
  6. Enable adaptive_readahead for better auto-tuning of readahead

See Also

Build docs developers (and LLMs) love