何时创建多个表而不是创建具有大量列的单个表才有意义。我知道表通常只有几个列族(1-2),每个列族可以支持1000多个列。
当HBase在单个表中可能包含大量列的情况下表现良好时,何时创建单独的表才有意义?
答案 0 :(得分:4)
在回答问题本身之前,让我首先说明一些起作用的主要因素。我将假设使用的文件系统是HDFS。
StoreFile本质上是一个包含KeyValues的排序文件。 KeyValue在逻辑上表示以下顺序:(RowLength,RowKey,FamilyLength,FamilyName,Qualifier,Timestamp,Type)。例如,如果您所在区域的CF只有两个KV,其键是相同的,但值在两列中,则这就是StoreFile的样子(除了它实际上是字节编码的,而且像length这样的元数据也是如此)如上所述存储):
Key1:Value1:Family1:Qualifier1:Timestamp1:Put
Key1:Value2:Family1:Qualifier2:Timestamp2:Put
StoreFile分为个块(默认为64KB),每个数据块中包含的键范围由多级索引建立索引。可以使用索引+二进制搜索在单个块内进行随机查找。但是,扫描必须在扫描所需的第一个程序段中找到开始位置之后,才能依次遍历特定程序段。
HBase是基于LSM树的数据库,这意味着它具有内存日志(称为 Memstore ),该日志会定期刷新到创建StoreFiles的文件系统中。对于特定列族,单个区域内的所有列都共享Memstore。
在处理从HBase读取数据/向HBase写入数据时涉及多个优化,但是上面给出的信息在概念上是正确的。鉴于以上陈述,与其他方法相比,具有多个列和多个表的优点如下:
具有多列的单个表
何时使用此:
多个表
何时使用:
另一种排序方式:单个表中有多个CF
从上面可以看到,两种方法都有其优点。如果您对多个列具有相同的行键结构(因此,您希望共享行键以提高存储效率或需要跨列进行事务处理)但数据非常稀疏(这意味着您只写/读),则选择将变得非常困难行键的一小部分列)。 在这种情况下,您似乎需要两全其美。这就是列族的用处。如果您可以将列集划分为逻辑子集,而这些子集通常只访问/读取/写入单个子集,或者您需要每个子集的存储级别配置(如TTL,存储类,编写繁重的压缩计划)等),则可以将每个子集设为一个列族。 由于特定列族的数据存储在单个文件(文件集)中,因此在读取列子集的同时不会降低扫描速度,您可以获得更好的局部性。
但是有一个问题:
请勿尝试不必要地使用列族。与它们相关联的是一个成本,由于区域级别的写锁定,监视等在HBase中的工作方式,HBase在10个以上的CF上表现不佳。仅当跨CF的列之间具有逻辑关系但通常不跨CF执行操作或需要为不同的CF具有不同的存储配置时,才使用CF。 如果您在所有列之间共享行键架构,则最好只使用一个包含所有列的CF,除非您的数据集非常稀疏,在这种情况下,您可能需要基于上述要点使用不同的CF或不同的表。>