Я искал хранилища значений ключей, которые поддерживают целые ключи и целые значения. LevelDB кажется хорошим вариантом, хотя я не могу найти информацию о том, поддерживаются ли целочисленные значения/ключи.
Можно ли хранить целочисленные ключи/значения в LevelDB?
Ответы (4)
В LevelDB можно хранить практически все что угодно. Вы предоставляете непрозрачные фрагменты данных в LevelDB через Slice
. Вот пример:
int intKey = 256;
int intValue = 256*256;
Slice key((char*)&intKey, sizeof(int));
Slice value((char*)&intValue, sizeof(int));
db->Put(leveldb::WriteOptions(), key, value);
И это почти все!
Однако следует отметить, что, хотя обычно можно хранить целые числа в LevelDB (как ключи, так и значения), они будут упорядочены через BytewiseComparator
, поэтому ваш ключ должен поддерживать побайтовое сравнение. Это также означает, что если вы полагаетесь на определенный порядок ключей, вы должны помнить о порядке следования байтов в системе.
Вы также можете написать собственный компаратор через интерфейс Comparator
. что позволит вам заменить BytewiseComparator
по умолчанию.
Во многих случаях лучше выбрать более сложную схему кодирования целочисленных ключей. Одним из вариантов является упаковка int в его представление с двумя дополнениями в char* (как предлагается в другом ответе на этот вопрос); Кодировка varint — еще одна (экономит место для небольших целых чисел, может хранить произвольные числа без верхней границы).
Чтобы расширить ответ Линка, отчасти потому, что я только что играл именно с этой вещью в рамках книги, которую я пишу, вы можете увидеть результаты BytewiseComparator, о которых он / она говорит ниже.
Другой подход состоит в том, чтобы преобразовать ваши двоичные целые числа в формат с обратным порядком байтов, чтобы они нормально сортировались с помощью компаратора по умолчанию. Это облегчает составление ключей. long flippedI = htonl(i);
Обратите внимание, что LevelDB работает очень быстро. Я провел тесты на iPhone4 с 50 000 записей с текстовыми ключами и вторичными ключами, то есть около 100 000 пар ключ/значение, и все заработало.
Очень легко написать собственный компаратор, который будет использоваться вашей базой данных навсегда и по-прежнему будет использовать ByteWiseComparator для ключей, отличных от ваших чисел. Самая большая проблема заключается в том, чтобы решить, какие ключи покрываются вашими пользовательскими правилами, а какие нет.
Тривиальным способом было бы сказать, что все нецелочисленные ключи имеют длину более 4 символов, поэтому вы предполагаете, что 4-байтовый ключ является целым числом. Это означает, что вам просто нужно убедиться, что вы добавили конечные пробелы или что-то еще, чтобы подтолкнуть это. Все это очень произвольно и зависит от вас, но помните, что у вас есть только две части информации: ключевое содержание и его длина. Для данного ключа нет других метаданных.
Часть результатов образца для стандартного компаратора с ключами int, начинающимися с 1 и возрастающими от 1 до 1000, с использованием базы данных со стандартным BytewiseComparator
Listing the keys in decimal and hex
256 ( 100)
512 ( 200)
768 ( 300)
1 ( 1)
257 ( 101)
513 ( 201)
769 ( 301)
2 ( 2)
258 ( 102)
514 ( 202)
770 ( 302)
3 ( 3)
259 ( 103)
515 ( 203)
771 ( 303)
...
254 ( fe)
510 ( 1fe)
766 ( 2fe)
255 ( ff)
511 ( 1ff)
767 ( 2ff)
LMDB имеет явную поддержку целочисленных ключей (и значений, если вы используете отсортированные дубликаты). http://symas.com/mdb
Когда БД сконфигурирована для целочисленных ключей, функции сравнения ключей также работают намного быстрее, поскольку они могут сравнивать пословно, а не только побайтно, как это делает сравнение, ориентированное на строки по умолчанию.
Отказ от ответственности: я являюсь автором LMDB. Конечно, это не меняет фактов.