我们使用MySQL来存储无模式数据(请参阅:使用关系数据库获取无模式数据,以获得受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
数据以构建异步物化视图(索引只是离线构建的表),但它们与当前的讨论无关......
我们应该如何序列化结构化数据(键值对)body
?
JSON或BSON很简单,因为每行重复字段名称.这使其具有灵活性的优势,但在空间效率方面也是一个很大的缺点(序列化数据中字段名称的每行开销).我们试图将内容保留在内存中,并且最小化内存和网络占用空间非常重要.我们可以在同一空间中放置的记录越多,查询的速度就越快.我们更喜欢相对较长的描述性字段名称,并缩短它们以使我的数据库更快是错误的!
最后,JSON/BSON对于我们的目的是不可行的,除非我们变得更复杂并将小键映射到与数据库对话的应用程序驱动程序中的更具描述性的键.这让我们思考......
虽然我们的数据库是无模式的,但实际上:1)没有太多不同类型的实体,2)同一类实体的版本不经常更改,3)当它们确实发生变化时,通常只是添加另一个领域.JSON/BSON没有版本控制的原生支持.
在版本控制和数据定义更改方面,Protocol Buffers和Thrift更加复杂.Thrift和Protocol Buffers都是将数据序列化到数据库的理想选择,而Thrift的设计使得编码格式是可扩展的.
协议缓冲区看起来是在无模式数据库中序列化数据的绝佳选择.
CouchDB和MongoDB(两个最流行的无模式数据库?)分别使用JSON和BSON,但我们找不到任何关于使用更高级的东西,比如Protocol Buffers,作为存储无模式数据的序列化格式.有些产品存储特定语言的对象版本(即将Java的Externalizable对象存储在数据网格中,或者在Ruby中使用MySQL进行NoSQL),但这些都很痛苦(尝试从其他平台访问它们,甚至从MySQL本身访问它们,并忘记版本控制).
是否有人在其数据库中存储更具互操作性的协议缓冲区,或在其无模式数据库中存储其他一些高级序列化格式?这是一个问题,除了JSON/BSON/XML的直接每行序列化,还是序列化特定语言的对象之外,是否还有其他选项.它甚至可行吗?我们错过了什么吗?对不起意识风格的叙事流!