Iterating over keys

To iterate over keys, we can use an Iterator, which can be obtained using the Txn.NewIterator() method. Iteration happens in byte-wise lexicographical sorting order.

  1. err := db.View(func(txn *badger.Txn) error {
  2. opts := badger.DefaultIteratorOptions
  3. opts.PrefetchSize = 10
  4. it := txn.NewIterator(opts)
  5. defer it.Close()
  6. for it.Rewind(); it.Valid(); it.Next() {
  7. item := it.Item()
  8. k := item.Key()
  9. err := item.Value(func(v []byte) error {
  10. fmt.Printf("key=%s, value=%s\n", k, v)
  11. return nil
  12. })
  13. if err != nil {
  14. return err
  15. }
  16. }
  17. return nil
  18. })

The iterator allows you to move to a specific point in the list of keys and move forward or backward through the keys one at a time.

By default, Badger prefetches the values of the next 100 items. You can adjust that with the IteratorOptions.PrefetchSize field. However, setting it to a value higher than GOMAXPROCS (which we recommend to be 128 or higher) shouldn’t give any additional benefits. You can also turn off the fetching of values altogether. See section below on key-only iteration.

Prefix scans

To iterate over a key prefix, you can combine Seek() and ValidForPrefix():

  1. db.View(func(txn *badger.Txn) error {
  2. it := txn.NewIterator(badger.DefaultIteratorOptions)
  3. defer it.Close()
  4. prefix := []byte("1234")
  5. for it.Seek(prefix); it.ValidForPrefix(prefix); it.Next() {
  6. item := it.Item()
  7. k := item.Key()
  8. err := item.Value(func(v []byte) error {
  9. fmt.Printf("key=%s, value=%s\n", k, v)
  10. return nil
  11. })
  12. if err != nil {
  13. return err
  14. }
  15. }
  16. return nil
  17. })

Key-only iteration

Badger supports a unique mode of iteration called key-only iteration. It is several order of magnitudes faster than regular iteration, because it involves access to the LSM-tree only, which is usually resident entirely in RAM. To enable key-only iteration, you need to set the IteratorOptions.PrefetchValues field to false. This can also be used to do sparse reads for selected keys during an iteration, by calling item.Value() only when required.

  1. err := db.View(func(txn *badger.Txn) error {
  2. opts := badger.DefaultIteratorOptions
  3. opts.PrefetchValues = false
  4. it := txn.NewIterator(opts)
  5. defer it.Close()
  6. for it.Rewind(); it.Valid(); it.Next() {
  7. item := it.Item()
  8. k := item.Key()
  9. fmt.Printf("key=%s\n", k)
  10. }
  11. return nil
  12. })