Проблема с производительностью в хранилище ключей 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 внутри.

Значительное время ожидания планировщика.

Как улучшить производительность префиксной итерации? Есть ли лучший подход для нашего варианта использования?

Спасибо

0 ответов

Другие вопросы по тегам