我们正在使用MySQL存储无模式数据(请参阅Using a Relational Database for Schemaless Data,以了解FriendFeed如何使用MySQL存储无模式数据的解决方案)。

一个大表保存了我们应用程序的所有实体:

CREATE TABLE entities (
  added_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
, id BINARY(16) NOT NULL
, body MEDIUMBLOB
, UNIQUE KEY (id)
) ENGINE=InnoDB ;

一些细节:
  • 存储的实体唯一需要的属性是id,它是一个16字节的UUID。实体的其余部分对数据库是不透明的。我们可以简单地通过将新属性存储在body中来更改“模式”。
  • 之所以存在added_id列,是因为InnoDB实际上以主键顺序存储数据行。 AUTO_INCREMENT主键可确保新实体在旧实体之后依次写入磁盘,这有助于读/写局部性(新实体比旧实体的读取频率更高)。
  • 我们的数据库将我们的无模式数据存储在body中。
  • 还有许多其他有趣的细节,例如“进入” body数据以构建异步的物化 View (索引只是离线构建的表),但它们与当前的讨论无关...

  • 我们应该如何在body中序列化结构化数据(键值对)?

    JSON或BSON很简单,因为字段名称对于每一行都是重复的。这给它带来了灵活性上的优势,但在空间效率上也有很大的劣势(序列化数据中字段名称的每行开销)。我们正在尝试将内容保留在内存中,在这里最小化内存和网络占用空间非常重要。我们可以在同一空间中容纳的记录越多,查询的速度就会越快。我们更喜欢相对较长的描述性字段名,而缩短它们以使我的数据库更快是错误的!

    最后,JSON/BSON不能用于我们的目的,除非我们变得更复杂,并且在与数据库通信的应用程序驱动程序中将小键映射到更具描述性的键。这让我们开始思考...

    尽管我们的数据库是无模式的,但实际上:1)实体种类不太多,2)同一实体的版本不经常更改,3)更改时,通常只是添加另一个领域。 JSON/BSON不支持版本控制。

    在版本控制和数据定义更改方面, Protocol Buffer 和Thrift更为复杂。 Thrift和Protocol Buffer都是将数据序列化到数据库中的最佳选择,并且Thrift的设计使编码格式可扩展。

    对于在无模式数据库中序列化数据, Protocol Buffer 看起来是一个不错的选择。

    CouchDB和MongoDB(两个最流行的无模式数据库?)分别使用JSON和BSON,但是我们找不到关于使用更高级的东西(如 Protocol Buffer )作为存储无模式数据的序列化格式的任何信息。有些产品可以存储特定语言的对象版本(例如,将Java的Externalizable对象存储在数据网格中,或者在Ruby中使用MySQL进行NoSQL处理),但是这些操作很麻烦(尝试从其他平台甚至从MySQL本身访问它们,而不用担心版本控制)。

    是否有人在他们的数据库中存储了更多可互操作的 Protocol Buffer ,或者在他们的无模式数据库中存储了一些其他高级序列化格式?这是一个问题,除了对JSON/BSON/XML进行逐行直接序列化或对特定语言的对象进行序列化之外,是否还有其他选择。可行吗?我们错过了什么吗?对于意识流叙事流感到抱歉!

    最佳答案

    如您所知,MongoDB和CouchDB对如何存储数据有强烈的意见。如果您正在寻找与存储无关的方法,则需要执行类似@Joshua建议的操作,并查看Cassandra或HBase。甚至这两个数据存储区都对如何存储数据(它们都基于Google's Bigtable)以及将数据存储在column families中具有意见。

    Riak使用 Protocol Buffer 作为将数据从应用程序序列化到数据存储中的一种方法。可能值得检查一下是否适合您的需求。您似乎在很大程度上计划进行单键查找,因此Riak可能是您解决方案的有力竞争者。

    关于mysql - 在无模式数据库中使用 Protocol Buffer 进行序列化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4272941/

    10-11 03:18
    查看更多