Как проверить, пуст ли leveldb

Предположим, вы не знаете точных ключей в базе данных leveldb.

Я попытался вставить 3 ключа и использовать GetApproximateSizes для диапазона ключей, результат неизменно равен нулю.

Так как же проверить, есть ли ключи в leveldb?


person nurettin    schedule 26.10.2013    source источник


Ответы (2)


Разве вы не можете просто использовать сканирование leveldb и распечатать все ключи и значения. Например, чтобы распечатать все ключи и значения в базе данных, вы можете сделать следующее:

  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
  for (it->SeekToFirst(); it->Valid(); it->Next()) {
    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
  }
  assert(it->status().ok());  // Check for any errors found during the scan
  delete it;

Теперь GetApproximateSizes дает нулевое значение, потому что вы только что вставили 3 ключа, и они все еще находятся в памяти (memtable) и еще не достигли файловой системы. Когда таблица памяти заполнена (по умолчанию 4 МБ), она создает первый файл на уровне 0. Поэтому она более полезна для большей базы данных и большего диапазона ключей.

В вашем случае единственным местом в файловой системе, в котором присутствуют данные, будет журнал повторов, и если ваши ключи являются строками, вы можете выполнить быструю проверку, вызвав «strings logfile» (в linux) в каталоге db, чтобы распечатать часть строки вашего keys как быстрый способ подтвердить, что данные вошли.

person jayadev    schedule 27.10.2013
comment
Конечно, я не перебирал все ключи только для того, чтобы убедиться, что база данных пуста, я просто сначала выполнил поиск, чтобы убедиться, что итератор действителен github.com/nurettin/pwned/blob/master/leveldb/leveldb.hpp#L153 но все же вы дали мне право идея - person nurettin; 19.06.2015

Мы используем leveldb в проекте NodeJS через высокоуровневый API levelUP. Используя API levelUP, вы можете запросить поток всех ключей и установить limit=1, чтобы ограничить ответ не более чем одним ключом. Если база данных пуста, вы получите пустой поток, иначе вы получите поток ровно с одним элементом.

var empty = true;
db.createReadStream(db, {
    keys: true,
    values: false,
    limit: 1
}.on('data', function(data) {
    empty = false;
}.on('end', function() {
    console.log('db is ' + (empty ? 'empty' : 'not empty')); 
});

Мы используем эту технику в модуле npm level-is-empty.

Поскольку вам нужно решение, использующее собственный API leveldb, я изучил, как levelUP реализует createReadStream() API.

В levelUP createReadStream реализуется с помощью итератора.

В levelDOWN собственный экземпляр Iterator создается здесь. Вызов next сообщает вам, есть ли у итератора больше данных или он завершен.

Я нашел пример использования встроенных итераторов leveldb здесь

По-видимому, метод итератора Valid() сообщает вам, есть ли еще ключи для чтения. Таким образом, просто вызвав SeekToFirst(), а затем Valid(), вы сможете узнать, есть ли вообще какой-либо ключ в базе данных.

Вот мое лучшее предположение (код не проверен, у меня нет под рукой компилятора C)

leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
it->SeekToFirst();
bool isEmpty = !(it->Valid());
delete it;
person regular    schedule 18.06.2015
comment
Что это за createReadStream? Я не нашел его в источниках leveldb. - person nurettin; 19.06.2015
comment
Извините, это API модуля levelup модуля npm, который находится поверх Nodejs-leveldb. привязки, называемые leveldown. Я ошибочно предположил, что вы используете NodeJS. Теперь я понимаю, что вы говорите о родном API leveldb. Я отредактирую свой ответ. - person regular; 25.06.2015
comment
Ха-ха, только что увидел ваш комментарий к принятому ответу, поэтому вы придумали то же решение. - person regular; 25.06.2015