HBase:创建多个表还是包含多个列的单个表?

时间:2018-07-13 13:49:22

标签: hadoop database-design hbase

何时创建多个表而不是创建具有大量列的单个表才有意义。我知道表通常只有几个列族(1-2),每个列族可以支持1000多个列。

当HBase在单个表中可能包含大量列的情况下表现良好时,何时创建单独的表才有意义?

1 个答案:

答案 0 :(得分:4)

在回答问题本身之前,让我首先说明一些起作用的主要因素。我将假设使用的文件系统是HDFS。

  1. 表被划分为称为区域的键空间的非重叠分区。
  2. 键范围->区域映射存储在称为meta的特殊单个区域表中。
  3. 一个区域的一个HBase列族中的数据存储在单个HDFS目录中。它通常是几个文件,但出于所有目的和目的,我们可以假定某个列族的区域数据存储在HDFS上的一个单独文件中,该文件称为StoreFile / HFile。
  4. 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
    
  5. StoreFile分为个块(默认为64KB),每个数据块中包含的键范围由多级索引建立索引。可以使用索引+二进制搜索在单个块内进行随机查找。但是,扫描必须在扫描所需的第一个程序段中找到开始位置之后,才能依次遍历特定程序段。

  6. HBase是基于LSM树的数据库,这意味着它具有内存日志(称为 Memstore ),该日志会定期刷新到创建StoreFiles的文件系统中。对于特定列族,单个区域内的所有列都共享Memstore。

在处理从HBase读取数据/向HBase写入数据时涉及多个优化,但是上面给出的信息在概念上是正确的。鉴于以上陈述,与其他方法相比,具有多个列和多个表的优点如下:

具有多列的单个表

  1. 由于前缀编码,磁盘上的压缩效果更好,因为Key的所有数据都存储在一起,而不是存储在表中的多个文件中。由于数据量较小,这也导致磁盘活动减少。
  2. 元数据表上的负荷较小,因为区域总数将变小。仅一个表将具有N个区域,而不是M个表将具有N * M个区域。这意味着更快的区域查找和对元表的低争用,这是大型集群所关心的。
  3. 当您需要为单个行键读取几列时,读取速度更快且IO放大较低(导致更少的磁盘活动)。
  4. 在为单个行键写入多列时,您将获得行级事务,批处理和其他性能优化的优势。

何时使用此

  1. 如果要跨多个列执行行级事务,则必须将它们放在单个表中。
  2. 即使您不需要行级事务,但您经常会为同一行键写入或查询多列。一个好的经验法则是,如果平均而言,您的列中有超过20%的列具有单个行的值,则应尝试将它们放到一个表中。
  3. 列太多时。

多个表

  1. 对每个表进行更快的扫描,如果扫描主要只关注一列,则IO放大率较低(记住扫描中的顺序查询将不必要地读取它们不需要的列)。
  2. 良好的数据逻辑分隔,尤其是当您不需要跨列共享行键时。对于一种类型的行键,只有一张表。

何时使用

  1. 当数据有明确的逻辑分离时。例如,如果您的行键架构在不同的列集中有所不同,则将这些列集放在单独的表中。
  2. 当只有一小部分列具有行键的值时(请参见下面的更好的方法)。
  3. 您要为不同的列集使用不同的存储配置。例如。 TTL,压缩率,阻止的文件计数,内存大小等。(在此用例中,请查看下面的一种更好的方法)。

另一种排序方式:单个表中有多个CF

从上面可以看到,两种方法都有其优点。如果您对多个列具有相同的行键结构(因此,您希望共享行键以提高存储效率或需要跨列进行事务处理)但数据非常稀疏(这意味着您只写/读),则选择将变得非常困难行键的一小部分列)。 在这种情况下,您似乎需要两全其美。这就是列族的用处。如果您可以将列集划分为逻辑子集,而这些子集通常只访问/读取/写入单个子集,或者您需要每个子集的存储级别配置(如TTL,存储类,编写繁重的压缩计划)等),则可以将每个子集设为一个列族。 由于特定列族的数据存储在单个文件(文件集)中,因此在读取列子集的同时不会降低扫描速度,您可以获得更好的局部性。

但是有一个问题

请勿尝试不必要地使用列族。与它们相关联的是一个成本,由于区域级别的写锁定,监视等在HBase中的工作方式,HBase在10个以上的CF上表现不佳。仅当跨CF的列之间具有逻辑关系但通常不跨CF执行操作或需要为不同的CF具有不同的存储配置时,才使用CF。 如果您在所有列之间共享行键架构,则最好只使用一个包含所有列的CF,除非您的数据集非常稀疏,在这种情况下,您可能需要基于上述要点使用不同的CF或不同的表。