在我们的应用程序中,我们使用std::map存储(键,值)数据并使用序列化将该数据存储在磁盘上.通过这种方法,我们发现磁盘I/O是性能瓶颈,使用密钥查找值不是很快.
我遇到了LevelDB并且正在考虑使用它.但我有一些问题.
std::map和LevelDB 之间的区别在于LevelDB是持久的并且std::map在内存中工作.这是否意味着磁盘I/O瓶颈对于levelDB来说会更成问题.更具体地说,任何人都可以解释一下LevelDB是否可能是更好的选择std::map?
PS:我尝试使用hash_maps但它看起来比较慢std::map
我有一组1亿多个字符串,每个字符串长达63个字符.我有很多磁盘空间和很少的内存(512 MB).我需要单独查询存在,并且不存储其他元数据.
我事实上的解决方案是BDB btree.有没有更好的选择?我知道leveldb和Kyoto Cabinet,但不熟悉以确定优势.
#include <leveldb/status.h>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
...
int arg_offset = 0;
leveldb::DB* db1;
leveldb::Options options;
options.error_if_exists = true;
options.create_if_missing = true;
options.write_buffer_size = 268435456;
leveldb::WriteBatch* batch;
...
if (db_backend == "leveldb")
{
// leveldb
LOG(INFO) << "Opening leveldb " << argv[arg_offset+2];
leveldb::Status status1 = leveldb::DB::Open(options, argv[arg_offset+2], &db1);
CHECK(status1.ok()) << "Failed to open leveldb " << argv[arg_offset+2];
batch = new leveldb::WriteBatch();
}
Run Code Online (Sandbox Code Playgroud)
上面的代码段会生成以下错误
$ g++ tools/convert_imageset_and_disparity.cpp -MMD -MP -pthread -fPIC -DCAFFE_VERSION=1.0.0-rc5 -DNDEBUG -O2 -DUSE_OPENCV -DUSE_LEVELDB -DUSE_LMDB -DWITH_PYTHON_LAYER -I/usr/include/python3.5m -I/usr/lib/python3.5/dist-packages/numpy/core/include -I/usr/local/include -I/usr/include/hdf5/serial …Run Code Online (Sandbox Code Playgroud) 我正在使用 leveldb 进行压力测试。
在util/env_poisx.cc : NewRandomAccessFile()
void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
Run Code Online (Sandbox Code Playgroud)
插入 300 万条数据(每条 100k)后。错误号说Cannot allocate memory。
为什么?
更多细节:
顶部:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
19794 root 20 0 290g 4.9g 4.7g S 98.6 7.8 2348:00 ldb
Run Code Online (Sandbox Code Playgroud)
自由-m:
total used free shared buffers cached
Mem: 64350 60623 3726 0 179 59353
-/+ buffers/cache: 1090 63259
Swap: 996 0 996
Run Code Online (Sandbox Code Playgroud)
ulimit -a:
core file size (blocks, -c) …Run Code Online (Sandbox Code Playgroud) 我通过 JNI 从 Java使用 LevelDB 。
我想提供一个数字(整数)键,并且能够按照该键的顺序迭代数据库。我遇到困难的地方是理解 LevelDb 的默认比较器实际上是如何工作的,以及如何将 int 编码为 a byte[],以使默认比较器按该值正确排序int。
LevelDb 文档指出:
前面的示例使用了 key 的默认排序函数,该函数按字典顺序对字节进行排序。
我已经用谷歌搜索过,但对如何将 an 实际编码int为按字典顺序排列的字节感到困惑?
注意:如果我提供自己的比较器,迭代时间大约会增加一倍,因为现在所有比较都必须在 JNI 边界上来回跳转,所以我不想这样做。
鉴于持久键/值存储的以下要求:
鉴于这种使用模式:
鉴于要求,最好的磁盘数据结构/算法是什么?
自定义实现能否超过基于 LSM(日志结构化合并)的实现(即 leveldb、rocksdb)的性能?
满足这些要求的高性能自定义实现在实现上是否也会相当简单?
最近在看leveldb的源码,但是对table中的rep struct和table_builder源码很迷惑。
因为我们可以直接将成员变量直接存储在类Table和类TableBuilder中。
但是作者为什么要做一个struct Rep,并将成员变量存放在struct Rep中呢?
我可以想出一个原因,因为 table 和 table_builder 会暴露给用户,所以我们想隐藏实现。这样对吗?或者还有其他一些我想念的想法,或者是某种设计模式?
谢谢
我想创建一个工具来删除rocksdb或leveldb中早于几天的所有数据,但我不知道如何启动它。
从crc32.hleveldb或rocksdb的注释中,我们可以找到这样的注释:
static const uint32_t kMaskDelta = 0xa282ead8ul;
// Return a masked representation of crc.
//
// Motivation: it is problematic to compute the CRC of a string that
// contains embedded CRCs. Therefore we recommend that CRCs stored
// somewhere (e.g., in files) should be masked before being stored.
inline uint32_t Mask(uint32_t crc) {
// Rotate right by 15 bits and add a constant.
return ((crc >> 15) | (crc << 17)) + kMaskDelta;
}
Run Code Online (Sandbox Code Playgroud)
那么,这意味着什么呢?为什么我们需要口罩?