В настоящее время я играю с RocksDB (C++), и мне было интересно узнать о некоторых показателях производительности, с которыми я столкнулся.
В целях тестирования ключи моей базы данных — это пути к файлам, а значения — это имена файлов. В моей базе данных около 2 миллионов записей. Я запускаю RocksDB локально на MacBook Pro 2016 (SSD).
В моем случае преобладают чтения. Полное сканирование ключей довольно распространено, как и сканирование ключей, включающее «значительное» количество ключей. (50%+)
Меня интересуют следующие наблюдения:
<сильный>1. Iterator
намного быстрее, чем вызов Get
при выполнении полного сканирования ключа.
Когда я хочу просмотреть все ключи в базе данных, я вижу улучшение производительности в 4-8 раз при использовании Iterator
вместо вызова Get
для каждого ключа. Использование MultiGet
не имеет значения.
В случае вызова Get
примерно 2M раз ключи были предварительно загружены в вектор и отсортированы лексикографически. Почему повторный вызов Get
намного медленнее, чем использование Iterator
? Есть ли способ сократить разрыв в производительности между двумя API?
<сильный>2. При извлечении примерно половины ключей производительность между использованием Iterator
и Get
становится незначительной.
Поскольку количество ключей для выборки уменьшается, выполнение нескольких вызовов Get
начинает занимать примерно столько же времени, сколько использование Iterator
, поскольку итератор расплачивается за сканирование ключей, которых нет в желаемом наборе ключей.
Есть ли какое-то «волшебное» соотношение, при котором это становится верным для большинства баз данных? Например, если мне нужно просканировать более 25% ключей, то вызов Get
будет быстрее, но если это 75% ключей, то вызов Iterator
будет быстрее. Но эти цифры просто «составлены» в результате грубого тестирования.
<сильный>3. Получение ключей в отсортированном порядке не повышает производительность.
Если я предварительно отсортирую ключи, которые хочу получить, в том же порядке, в котором их вернет Iterator
, это, по-видимому, не ускорит вызов Get
несколько раз. Почему это? В документации упоминается, что перед пакетной вставкой рекомендуется сортировать ключи. Разве Get
не выигрывает от того же упреждающего кэширования, что и Iterator
?
<сильный>4. Какие настройки рекомендуются для случаев с большим объемом чтения?
Наконец, есть ли какие-либо специальные настройки, рекомендуемые для случая использования с интенсивным чтением, который может включать сканирование значительного количества ключей одновременно?
macOS 10.14.3, MacBook Pro 2016 SSD, RocksDB 5.18.3, Xcode 10.1
for
, который либо используетIterator
, либо делает несколько вызововGet
. Значения в обоих случаях считываются в вектор только для того, чтобы предотвратить какое-либо неактивное поведение. Каждый цикл выполняется несколько раз подряд для учета любого кэширования диска. Для меня это не микро-бенчмаркинг, а скорее грубый бенчмаркинг, и я вижу разницу более чем в 100% между двумя API, отсюда и запрос. - person kennyc   schedule 26.03.2019-Os
. - person kennyc   schedule 26.03.2019