我需要存储一些数据,这些数据遵循将“id”映射到几列的完整表(具有多行)的简单模式(即一些整数值[u,v,w])。其中一个表的大小将是几KB。基本上我需要的是存储一些中间结果的持久缓存。
这可以很容易地实现为简单的sql,但是有一些问题,即我需要尽可能地在磁盘上压缩这个结构的大小。 (因为我正在存储的值的数量)另外,它不是事务性的,我只需要编写一次并简单地读取整个表的内容,因此关系数据库实际上不是很合适。
我想知道是否有人有任何好的建议?出于某种原因,我似乎无法想出一些体面的atm。特别是在java中使用API的东西会很好。
答案 0 :(得分:3)
这听起来像.... new ObjectOutputStream(new FileOutputStream(STORAGE_DIR + "/" + key + ".dat");
!!
说真的 - 最简单的方法是为每个要存储的数据表创建一个文件,将数据序列化并在需要读取时使用键作为文件名进行查找。
在一个体面的文件系统上,写入可以是原子的(通过写入临时文件,然后重命名文件);读/写速度以MBs /秒为单位测量;通过创建一个像STORAGE_DIR + "/" + key.substring(0,2) + "/" + key.substring(0,4) + "/" + key
这样的简单目录树可以使查找更加高效,如果您的文件系统使用索引目录,那么它应该仍然可以有效地存储数百万条目,并且效率更高;最后,为了实现更快的检索,实现内存支持的LRU缓存是微不足道的。
关于压缩 - 您可以在存储之前使用Jakarta的commons-compress来对数据进行gzip甚至bzip2压缩。但这是一个优化问题,根据您的应用程序和可用磁盘空间,您可能最好将CPU周期投入其他地方。
以下是我做的示例实现:http://geek.co.il/articles/geek-storage.zip。它使用一个简单的界面(它远非干净 - 它只是对概念的演示),它提供了使用设定的最大大小从缓存中存储和检索对象的方法。高速缓存未命中转移到用户实现以进行处理,并且高速缓存将定期检查它是否未超出存储要求并将删除旧数据。
我还包括一个MySQL支持的完成实现和一个比较基于磁盘和基于MySQL的实现的基准。在我的家用机器(旧的Athlon 64)上,磁盘基准测试得分比封装基准测试中的MySQL实现速度快两倍(9.01秒对18.17秒)。尽管数据库实现可能会稍微调整一下以获得更好的性能,但我相信它可以很好地证明这个问题。
您可以根据需要随意使用。
答案 1 :(得分:2)
我使用EHCache,它被Hibernate和其他Java EE库使用,并且非常简单有效:
添加表格:
List<List<Integer>> myTable = new(...)
cache.put(new Element("myId", myTable));
阅读:
List<List<Integer>> myTable = (List<List<Integer>>) cache.get("myId").getObjectValue();
答案 2 :(得分:1)
答案 3 :(得分:1)
Apache Derby可能是合适的。
列出了其他选项答案 4 :(得分:0)
似乎 Key =&gt;值数据库是您搜索的内容。
也许SuperCSV是最适合您的框架!
如果您不想使用关系数据库,可以使用JAXB将对象存储为XML文件!
还有其他库如XStream
如果您更喜欢XML,那么请使用JAXB或XStream。否则,您应该查看CSV库,例如SuperCSV。能够使用序列化java文件生活的人可以使用像Guss所说的默认持久性机制。直接Java持久性可能是最快的方式。
答案 5 :(得分:0)
您可以使用JOAFIP http://joafip.sourceforge.net/ 它使您能够将所有数据模型放入文件中,并且可以访问它,更新它,而无需在内存中重新加载。
答案 6 :(得分:0)
如果你有几个KB,我不明白为什么你需要“尽可能地在磁盘上压缩这个结构的大小”鉴于181 MB的磁盘空间花费1美分,我会建议任何事情不到这一点不值得花太多时间担心。
但是要回答您的问题,您可以在编写文件时压缩文件。与ObjectOutputStream一样,您可以使用XMLExcoder序列化地图。这比仅使用ObjectOutputStream更紧凑,如果解压缩文件,您将能够读取或编辑数据。
XMLEncoder xe = new XMLEncoder(
new GZIPOutputStream(
new FileOutputStream(filename+".xml.gz")));
xe.writeObject(map);
xe.close();