在设计 HBase 结构时, 需要考虑以下一般性原则:
? 访问 HBase 数据最高效的方式是使用基于行键的 Get 或 Scan 操作。 HBase 不支持任何二级键/索引。 这意味着在理想情况下, 行键的设计应该包含特定表所需要的全部访问模式。 这通常意味着需要使用复合行键来容纳更多的数据访问模式
? 一条一般性的原则是将每个表的列族数限定为不超过10~ 15(记住 HBase 将每个列族保存在独立的文件中, 因此大量的列族会导致需要读取和合并多个文件)。 同样,基于这样一个事实, 即列族名会显式地与每个列名保存在一起(参见表2-4), 因此应该最小化列族的大小。 如果列中数据量小的话, 通常推荐使用单个字母的名字。
? 尽管 HBase 对给定行中列的大小不强加任何限制, 但应该考虑以下问题:
• 行不是可分割的。 其结果是, 较大的列数据(接近于域大小)通常表明该类型数据不应该保存在 HBase 中。
• 每个列的值均与其元数据一起保存(行键、 列族名、 列名), 这意味着非常小的列数据会导致较低的存储利用率(即元数据比实际表数据占用了更多的空间)。 这也意味着不应该使用较长的列名。? 在高而窄(上百万的键与有限数量的列)和扁而宽(有限数量的键与上百万的列)的表设计之间进行选择时, 通常推荐使用前者。 这是由于以下原因:
• 在极端情况下, 扁而宽的表可能终结为每个域上的一行, 这对于性能和可扩展性都是不利的。
• 与大量的读操作相比, 表扫描通常更高效。 其结果是, 假如仅需要行数据的一个子集, 则高而窄的设计提供更好的整体性能。
HBase 设计的主要优势之一是在多台域服务器之间分布式地执行请求。 然而, 利用该设计的优势并确保在应用执行时没有“ 热点” (高负载的)服务器出现, 则可能需要特殊的
行键设计方案。 通常建议避免将单调递增序列(例如, 1、 2、 3, 或时间戳)作为大量 Put 操作的行键。 通过将键值随机化使得它们不按顺序排列, 可以缓解由于单调递增键引发的单个域上的拥塞。
数据本地性也是 HBase Get/Scan 操作在设计上的一个重要考虑因素。 应该将经常一起读取的行放置在一起, 这意味着它们必须有相邻的键。在大量 Scan 操作的情况下, 一般的规则是使用顺序的键, 尤其是可以将大数据块导入用于数据填充的情况。 对于大量并行写操作(随机的、 单独的键访问), 推荐使用随机键。