我正在开发一个项目,该项目使用HBase存储用户的键/值信息。我们正在重新设计我们正在使用的HBase架构。正在讨论的两个选项是:
这两种方法的设计权衡是什么?一个比另一个好吗?它们是否有任何理由不使用Avro或Thrift存储数据?
答案 0 :(得分:9)
总之,我倾向于为每个键使用不同的列。
1)显然,你强调客户端使用Avro / Thrift,这是另一种依赖。这种依赖性意味着您可以消除某些工具的可能性,例如期望在没有转换的情况下在数据中查找值的BI工具。
2)在avro / thrift计划下,你几乎被迫将整个价值带到了线上。根据连续的数据量,这可能无关紧要。但是,如果您只对“城市”字段/列限定符感兴趣,则仍需要“付款”,“信用卡信息”等。这也可能会带来安全问题。
3)如果需要,Avro / Thrift的更新将更具挑战性。示例:您决定添加'hasIphone6'键。 Avro / Thrift:您将被迫删除该行并使用添加的字段创建一个新行。在列方案下,附加一个新条目,仅包含新列。对于单行而言,并不大,但如果这样做到十亿行,则需要进行大规模的压缩操作。
4)如果已配置,您可以在HBase中使用压缩,这可能会超过avro / thrift序列化,因为它可以压缩列族,而不仅仅是单个记录。
5)像HBase这样的BigTable实现非常适用于非常宽的稀疏表,因此不会像预期的那样出现性能损失。
答案 1 :(得分:3)
对此的正确答案有点复杂,所以我先给你tl; dr先生。
使用Avro / Thrift / Protobuf
您需要在记录与列中打包的字段数之间取得平衡。
您通常希望将经常一起访问的字段(原始问题中的“键”)放入类似avro记录的内容中,因为正如cmonkey所提到的,您不希望获得额外数据的开销,这是您赢得的额外数据使用。
通过使您的行非常宽,由于HFiles的存储方式,您在获取列的子集时会增加搜索时间。再次,确定什么是最佳,归结为您的访问模式。
我还想指出,通过使用像avro这样的东西,你也可以为自己提供进化。您不需要删除该行并使用包含新字段的记录重新添加该行。 Avro具有向后兼容性和向前兼容性的规则。这实际上使您的生活变得更加轻松,因为您可以读取新旧记录,而无需重写数据或强制更新旧客户端代码。
你应该几乎总是在HBase中使用压缩(SNAPPY总是一个不错的选择)。