我计划为json数据设计hbase表。
由于我不太了解hbase的概念,我想知道为下面提到的json类型设计表的最佳方法是什么。
虚线是json数据中的逻辑划分:这意味着一个记录有一个rowkey,它是uid,然后有粗体的request部分,斜体的response部分。在分类下有一个类似数组的结构。我正在考虑为每个逻辑组创建3个列族。但是如何将类似数组的结构(“问题原因”)存储到hbase表中。hbase除了binary之外还有其他特定的数据类型吗??
{
"uid": "abc2342",
-----------------------------------
"req1": sometext,
"res1": sometext,
"matter": "point1",
"body": "point2",
-------------------------------------
"response": null,
"validity": null
---------------------------------------
"classification": "Problems",
"Problem reasons": [
"Address Not found",
"Invalid Phone Number",
"Invalid Email"
]
},
3条答案
按热度按时间trnvg8h31#
hbase是一只愚蠢的野兽,你必须这样对待它。它只是一个低级别的索引存储。
您应该遵循一条规则—模式的存储方式应该是访问,而不是存储。根据其他注解,您应该使用req1生成rowkey。
但请注意!req1必须是均匀分布的,而不是二进制序列值。如果必须的话,用种子。
如果您使用rowkey作为一个整体访问json对象,那么只需将所有内容转储为二进制字符串、bson或某个序列化程序就足够了。如果更新不是并发的,那么更新的数量其实并不重要。
如果您希望能够使用键或同时添加/更改值来引用数据的一个子集,那么应该将它们分开。
根据您的示例,可以轻松地将值拆分为3列族:
请求(列如下所示)req:req1, req:uid and 以此类推)
响应(列如下所示)res:validity and 以此类推)
分类
在分类列族中,可以将值拆分到最低级别:
cl:classification列可以识别分类的类型
如果您的分类列表是合理和有限的,那么您可以通过分类-列族问题来命名列族
然后可以将数组值添加为列值或列名:
problem:1 =>“找不到地址”
problem:addressnotfound =>1-这种方法的主要好处是它可以很好地处理并发更新。
cl:reason1=>“找不到地址”
anauzrmj2#
hbase只有二进制文件。您必须自己序列化和反序列化数据。hbase
Bytes
课堂可以帮助你。Bytes.toBytes((short) 5)
). 对于数组,您必须考虑如何计划查询它,从而找出最适合您的格式。存储字符串数组的一种简单方法是使用字符串本身不允许的分隔符将它们连接起来。也可以将其作为json转储。对于您的模式,另一个重要的考虑因素是关键。通常您希望有一个统一的随机密钥,这样您就不会得到可能降低性能的热点。一个简单的方法是散列字符串键并使用散列的字节。
对于柱族:
实际上,所有列族成员都存储在文件系统中。由于调整和存储规范是在柱族级别完成的,因此建议所有柱族成员具有相同的一般访问模式和大小特征。
ibm有一个很好的文档,其中包含一些经验法则:
hbase表由列族组成,这些列族是列的逻辑和物理分组。一个族中的列与另一个族中的列分开存储。如果有不经常查询的数据,请将该数据指定给单独的列族。
每行的列族和列限定符名称都是重复的。因此,名称应尽可能短,以减少hbase存储和读取的数据量。例如,使用f:q代替mycolumnfamily:mycolumnqualifier.
因为列族存储在单独的hfiles中,所以要尽量减少列族的数量。您还需要减少列族的数量,以减少memstore刷新的频率和压缩的频率。而且,通过使用尽可能少的列族,可以缩短加载时间并减少磁盘消耗。
hgb9j2n63#
我假设您的结构是每个用户都有一个请求、一个响应和几个问题。
如果是这样,就把uid设为rowkey。行键设计是hbase模式设计中最重要的部分。这是因为hbase基于rowkey对数据进行切分,并控制如何查找数据。为了避免热插拔,您可能需要在键的前面预先添加一个uid哈希。例如,你可以让你的钥匙看起来像这样
hash(UID):UID
或者f97h23:user123
.现在开始你的下一个问题。hbase只存储字节。它不关心那些字节是什么。你的程序需要知道你存储的字节是什么意思。hbase不知道除计数器以外的数据类型,但我们将忽略这些类型。
这个表看起来相当简单,所以我将把其余的json字段分别设置为一列。对于数组,我在列中做了一些类似于分隔列表的事情。
Address Not found,Invalid Phone Number,Invalid Email
. 无论何时使用这样的方案,都要确保在数据中使用非法的分隔字符,或者使用转义方案。在大多数情况下,我认为没有理由单独列族。似乎每行有少量的数据,而且您没有提到不同的访问模式,这使我假设您在查询uid时基本上只获取每个字段。如果确实如此,您甚至可以有一列“json”来存储上面的json字符串。这样做的缺点是需要序列化和反序列化json。
有关用例的更多信息将有助于指导设计。比如:
你能大致描述一下你用这个数据库解决了什么问题吗?
你总是读所有的专栏,还是仅仅读一些?
您希望总共有多少行?
您通常是追加新记录,还是更新现有记录?
从读到写的混合是什么?
性能要求是什么?