Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite 嵌入式密钥值db与每个密钥只存储一个文件?_Sqlite_Go_Embedded Database_Rocksdb - Fatal编程技术网

Sqlite 嵌入式密钥值db与每个密钥只存储一个文件?

Sqlite 嵌入式密钥值db与每个密钥只存储一个文件?,sqlite,go,embedded-database,rocksdb,Sqlite,Go,Embedded Database,Rocksdb,我对嵌入式键值数据库的优势感到困惑,而不是一个简单的解决方案,即每个键只在磁盘上存储一个文件。例如,RocksDB、Badger、SQLite等数据库使用了B+树和LSM等奇特的数据结构,但似乎获得了与此简单解决方案大致相同的性能 例如,Badger(嵌入式db中速度最快的)需要编写一个条目。相比之下,从头创建一个新文件并向其中写入一些数据需要150个麦克风,而无需优化 编辑:为了澄清,这里是一个键值存储的简单实现,我正在与最先进的嵌入式dbs进行比较。只需将每个键散列为一个字符串文件名,并将相

我对嵌入式键值数据库的优势感到困惑,而不是一个简单的解决方案,即每个键只在磁盘上存储一个文件。例如,RocksDB、Badger、SQLite等数据库使用了B+树和LSM等奇特的数据结构,但似乎获得了与此简单解决方案大致相同的性能

例如,Badger(嵌入式db中速度最快的)需要编写一个条目。相比之下,从头创建一个新文件并向其中写入一些数据需要150个麦克风,而无需优化

编辑:为了澄清,这里是一个键值存储的简单实现,我正在与最先进的嵌入式dbs进行比较。只需将每个键散列为一个字符串文件名,并将相关值存储为该文件名处的字节数组。读取和写入每个约150个麦克风,这比Badger的单次操作速度快,与批处理操作相当。此外,磁盘空间很小,因为除了实际值之外,我们不存储任何额外的结构


这里我肯定遗漏了一些东西,因为人们实际使用的解决方案是超级花哨的,并且使用bloom过滤器和B+树进行了优化。

但Badger并不是要写“一个”条目:

我的写作真的很慢。为什么? 您是否正在为每个密钥更新创建一个新事务?这将导致非常低的吞吐量

要获得最佳写入性能,请使用单个
DB.Update()
调用在事务中批处理多个写入操作
您还可以从多个goroutine同时进行多个此类DB.Update()调用

这导致:

我在Go中寻找快速存储,所以我的第一次尝试是BoltDB。我需要很多单写事务。博尔特的速度大约为240转/秒

我刚刚测试了Badger,得到了一个疯狂的10k rq/s。我只是感到困惑

这是因为:

与B+树相比,LSM树在写操作方面具有优势。
此外,值单独存储在值日志文件中,因此写入速度更快

你可以


其中一个要点(通过简单的文件读/写很难复制)是:

键值分离 LSM树的主要性能成本是压实过程。在压缩过程中,多个文件被读入内存、排序并写回。对于键查找和范围迭代,排序对于高效检索至关重要。通过排序,键查找将只需要访问每个级别最多一个文件(不包括级别0,我们需要检查所有文件)。迭代将导致对多个文件的顺序访问

每个文件大小固定,以增强缓存。值往往大于键。将值与键一起存储时,需要压缩的数据量会显著增加

在Badger中,只有一个指向值日志中的值的指针存储在键旁边。Badger对密钥采用增量编码,以进一步减小有效大小。假设每个键16字节,每个值指针16字节,一个64MB的文件可以存储200万个键值对


您的问题假设唯一需要的操作是单次随机读写。这些是日志结构合并(LSM)方法(如Badger或RocksDB)的最坏情况。范围查询返回范围中的所有键或键值对,它利用顺序读取(由于文件中排序的kv相邻)以非常高的速度读取数据。对于Badger,如果执行仅关键点或小值范围的查询,您将获得最大的好处,因为它们存储在LSM中,而大值附加在不一定排序的日志文件中。对于RocksDB,您将获得快速kv对范围查询


前面的答案在某种程度上说明了写操作的优势——缓冲的使用。如果您写入了许多kv对,而不是将它们存储在单独的文件中,那么LSM方法会将它们保存在内存中,并最终在文件写入中刷新它们。没有免费的午餐,因此必须进行异步压缩,以删除覆盖的数据并防止检查过多的文件进行查询。

前面已经回答过。与这里提供的其他答案基本相似,但有一点很重要,即文件系统中的文件不能占用磁盘上的同一块。如果您的记录平均比典型的磁盘块大小(4-16 KiB)小得多,那么将它们作为单独的文件存储将产生巨大的存储开销。

谢谢您的回复!对磁盘写入进行批处理可以提高速度,这是有道理的,但即使是这些批处理写入也比我想象的要慢。您引用的10k/秒仍然是每次写入100毫秒,这与每次写入打开一个单独的文件一样慢。@rampatowl尽管如此,设计文档显示了不仅仅是写入的其他优势。不过,读/写时间似乎应该是比较嵌入式键值数据库的主要方式。我只是感到惊讶的是,最先进的数据结构的速度几乎与为每个键打开自己的文件一样快(每次读/写100个麦克风)。我遗漏了什么吗?@rampatowl这不是关于读/写文件,而是关于条目查找优化。我编辑了我的原始帖子并进行了澄清。我之所以将Badger的操作时间与文件读/写时间进行比较,是因为您可以实现一个最小的键值存储,每个键一个文件,其中每个条目查找所需的时间与单个文件访问所需的时间一样长(没有额外的数据结构)。数据库不仅仅是将内容写入磁盘的问题,而是如何管理它们的问题(事务、查询、更新、排序等)。如果您将内容存储到原始文件中(例如,每个密钥一个磁盘),则除非您自己实现这些功能,否则您将不具备这些优势。此外,每个文件都有占用磁盘空间的元数据。如果您的内容大小小于元数据大小,则“每个密钥一个文件”解决方案