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

spd*_*cbr 5 database-design hadoop hbase

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

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

Ash*_*uri 7

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

  1. 一个表被划分为称为区域的键空间的非重叠分区。
  2. 键范围->区域映射存储在称为meta的特殊单个区域表中。
  3. 一个区域的一个HBase列族中的数据存储在单个HDFS目录中。它通常是几个文件,但是出于所有目的和目的,我们可以假定某个列族的区域数据存储在HDFS上的一个单独的文件中,该文件称为StoreFile / HFile。
  4. StoreFile本质上是一个包含KeyValues的排序文件。KeyValue在逻辑上表示以下顺序:(行长度,行键,家庭长度,家庭名称,限定符,时间戳,类型)。例如,如果您的区域中只有两个KV,而CF的键是相同的,但值在两列中,则这就是StoreFile的样子(除了它实际上是字节编码的,而且像length这样的元数据也是如此)如上文所述存储):

    Key1:Value1:Family1:Qualifier1:Timestamp1:Put
    
    Key1:Value2:Family1:Qualifier2:Timestamp2:Put
    
    Run Code Online (Sandbox Code Playgroud)
  5. StoreFile分为多个(默认为64KB),每个数据块中包含的键范围由多级索引建立索引。可以使用索引+二进制搜索在单个块内进行随机查找。但是,在将开始位置定位在扫描所需的第一个块中之后,扫描必须依次通过特定的块。

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

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

单表多列

  1. 由于使用了前缀编码,因此磁盘压缩效果更好,因为密钥的所有数据都存储在一起,而不是存储在跨表的多个文件中。由于较小的数据大小,这也导致磁盘活动减少。
  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或不同表。