Проблема с производительностью в хранилище ключей Golang (Badger DB)
В badgerDB у нас есть миллиарды ключей типа
string
и значения типа . В нашем случае длина
HashValueList
может быть в миллионах. Мы должны закодировать ключ и значение в
[]byte
перед вставкой в BadgerDb; мы используем
encoding/gob
упаковка. Итак, всякий раз, когда нам нужны значения, мы должны снова их декодировать. Этот процесс декодирования вызывает накладные расходы в нашем случае.
type HashValue struct {
Row_id string
Address string
}
type HashValueList []HashValue
Чтобы уменьшить накладные расходы на декодирование, мы меняем наш дизайн на префиксную итерацию. С итерацией префикса мы сохранили каждое из значений из нашей коллекции как отдельную пару Badger KV, а не один ключ с большим значением. Префикс ключа будет исходным ключом хеш-значения. затем нам нужно будет добавить суффикс, чтобы обеспечить уникальность набора значений из исходного набора. Итак, в вашей исходной схеме есть что-то вроде:
k1 -> [v1, v2, v3, ..., vn]
...
km -> [w1, ..., wm]
Теперь есть что-то вроде:
k1@1 -> v1
k1@2 -> v2
k1@3 -> v2
...
k1@n -> vn
...
km@1 -> w1
...
km@m -> wm
Чтобы найти значения из БД, у нас есть n горутин, которые считывают
KeyChan
канал и запись значений в
ValChan
.
func Get(db *badger.DB, KeyChan <-chan string, ValChan chan []byte) {
var val []byte
for key := range KeyChan {
txn := db.NewTransaction(false)
opts := badger.DefaultIteratorOptions
opts.Prefix = []byte(key)
it := txn.NewIterator(opts)
prefix := []byte(key)
for it.Rewind(); it.ValidForPrefix(prefix); it.Next() {
item := it.Item()
val, err := item.ValueCopy(val[:])
ValChan <- val
item = nil
if err != nil {
fmt.Println(err)
}
}
it.Close()
txn.Discard()
}
}
В итерации префикса функция Get через некоторое время становится очень медленной. Мы собрали 5-секундную трассировку выполнения, и результаты приведены ниже:
Здесь
github.com/dgraph-io/badger/v3.(*Iterator).fill.func1 N=2033535
Создание огромного количества Goroutine внутри.
Значительное время ожидания планировщика.
Как улучшить производительность префиксной итерации? Есть ли лучший подход для нашего варианта использования?
Спасибо