【问题标题】:Better to store data in RAM, text file, or database最好将数据存储在 RAM、文本文件或数据库中
【发布时间】:2013-05-26 18:40:38
【问题描述】:

我正在做一个项目,我正在使用由向量编码的单词,这些单词大约有 2000 个浮点数。现在,当我将这些与原始文本一起使用时,我需要检索每个单词遇到的向量并对其进行一些计算。不用说,对于大词汇量(约 100k 词),这需要很大的存储空间(文本文件中大约 8 GB)。

我最初有一个系统,我将大文本文件拆分为较小的文件,然后对于特定的单词,我读取它的文件,并检索它的向量。这太慢了,就像你想象的那样。

接下来我尝试将所有内容读入 RAM(大约需要 40GB RAM),因为一旦读入所有内容,它会非常快。但是,读入需要很长时间,缺点是我只能使用某些具有足够空闲 RAM 的机器来执行此操作。但是,一旦加载数据,它就比其他方法快得多。

我想知道数据库将如何与这些方法进行比较。检索会比 RAM 方法慢,但不会有开销要求。此外,任何其他想法都会受到欢迎,我自己也有其他想法(即缓存,使用将所有内容加载到 RAM 中的服务器等)。我可能会对数据库进行基准测试,但我想我会在这里发帖看看其他人要说什么。

谢谢!

更新

我采纳了泰勒的建议。尽管就我而言,我认为 BTree 是不必要的。我只是散列了单词和它们的偏移量。然后我可以在运行时查找一个单词并读取它的向量。我缓存了文本中出现的单词,因此每个向量最多只读取一次,但这节省了读取和存储不需要的单词的开销,使其优于 RAM 方法。

仅供参考,我使用了 Java 的 RamdomAccessFile 类并使用了 readLine()、getFilePointer() 和 seek() 函数。

感谢所有为本主题做出贡献的人。

更新 2

要获得更多性能改进,请查看以下缓冲的 RandomAccessFile: http://minddumped.blogspot.com/2009/01/buffered-javaiorandomaccessfile.html

显然,来自 RandomAccessFile 的 readLine 非常慢,因为它逐字节读取。这给了我一些不错的改进。

【问题讨论】:

  • 以二进制文件格式存储数据怎么样?
  • 需要更多信息来回答这个问题。你只需要检索,存储新数据,删除和更新数据呢?您是每个请求只检索一个,还是有应该检索多个结果的查询?就速度而言,什么对您来说更重要?获取数据还是更新数据?更多信息,否则这是一个悬而未决的问题..
  • 如果您创建适当的索引,数据库应该最适合您。我会选择 SQLite。
  • 为什么要保存整个单词?您不能只保存单独的字母,然后根据某些元数据创建单词吗?
  • @G.Y 是的,我只需要检索 - 无需更新。现在我一次检索一个,尽管我可以要求多个(即一个句子中的所有单词)。

标签: database file text words


【解决方案1】:

一般来说,任何自定义编码都应该比通用数据库快得多,前提是您已经高效地对其进行了编码。

有特定的 C 库可以使用 B 树来解决此问题。过去有一个名为“B-trieve”的著名库,因为速度快而非常受欢迎。在这个应用程序中,B-tree 将比在数据库中胡乱摆弄更快、更容易。

如果您想要获得最佳性能,您可以使用称为后缀树的数据结构。有些库旨在创建和使用后缀树。这将为您提供最快的单词查找。

在任何一种情况下,都没有理由将整个数据集存储在内存中,只需将 B 树(或后缀树)与内存中的数据的偏移量存储在一起即可。这将需要大约 3 到 5 兆字节的内存。当您查询树时,您会得到一个偏移量。然后打开文件,向前寻找偏移量并从磁盘读取向量。

【讨论】:

  • 谢谢我不知道这样的方法。然而不幸的是,一切都是用java编码的,所以我认为内存偏移方法不可行(尽管我可能错了)。
  • 偏移量不在内存中,而是在磁盘中。当您在 Java 中从磁盘读取文件时,您将其作为 SeekableByteChannel 打开。 b-tree 存储每个向量的偏移量。所以,假设你的词是“apple”,那么 b-tree 会说:“apple 的向量位于文件偏移量 35235857634”,然后你打开文件,寻找那个偏移量并从文件中读取向量。跨度>
  • 仅供参考,这是一些教授网站上的一个非常简单的 BTree 实现:cs.oswego.edu/~mohammad/classes/csc365/Btree/Btree.java。 Braindead简单,复制和粘贴。如果你谷歌,你可以找到很多其他人。
【解决方案2】:

您可以使用一个简单的基于文本的索引文件,只将单词映射到索引,另一个文件只包含每个单词的原始矢量数据。最初,您只需将索引读取到哈希映射,该哈希映射将每个单词映射到数据文件索引并将其保存在内存中。如果需要某个单词的数据,则计算数据文件中的偏移量(2000 * 32 * index)并根据需要读取。您可能希望将这些数据缓存在 RAM 中(如果您使用的是 java 可能只是使用弱映射作为起点)。

这基本上是实现您自己的原始数据库,但它可能仍然是可取的,因为它避免了数据库设置/部署的复杂性。

【讨论】:

  • 正是我的解决方案;考虑到替代结构/存储方法所需的开销。
猜你喜欢
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多