为什么不建议在 HBase 中使用过多的列族
我们知道,一张 HBase 表包含一个或多个列族。
HBase 的官方文档中关于 HBase 表的列族的个数有两处描述:
A typical schema has between 1 and 3 column families per table. HBase tables should not be designed to mimic RDBMS tables. 以及 HBase currently does not do well with anything above two or three column families so keep the number of column families in your schema low.
上面两句话其实都是说一件事,HBase 中每张表的列族个数建议设在1~3之间。
其实,HBase 支持的列族个数并没有限制,但为什么文档建议在1~3之间呢?
我将从几个方面来阐述这么做的原因。
列族数对 Flush 的影响
在 HBase 中,调用 API 往对应的表插入数据是会写到 MemStore 的,而 MemStore 是一种内存结构,每个列族对应一个 MemStore(和零个或多个 HFile)。如果我们的表有两个列族,那么相应的 Region 中存在两个 MemStore,如下图:
![](https://ssl.iteblog.com/pic/hbase/HBase_MemStore-iteblog.png)
从上图可以看出,越多的列族,将会导致内存中存在越多的 MemStore;
而储存在 MemStore 中的数据在满足一定条件的时候将会进行 Flush 操作;
每次 Flush 的时候,每个 MemStore 将在磁盘生产一个 HFile 文件,如下:
![](https://ssl.iteblog.com/pic/hbase/HBase_Flush-iteblog.png)
这样会导致越多的列族最终持久化到磁盘的 HFile 越多。更要命的是,当前 Flush 操作是 Region 级别的(当然,从HBase 1.1,HBase 2.0 开始 Flush 已经可以设置成列族级别的了),也就是说, Region 中某个 MemStore 被 Flush,同一个 Region 的其他 MemStore 也会进行 Flush 操作。当表有很多列族,而且列族之间数据不均匀,比如一个列族有100W行,一个列族只有10行,这样会导致持久化到磁盘的文件数很多,同时有很多小文件,而且每次 Flush 操作也涉及到一定的 IO 操作。
为了解决每次 Flush 都对整个 Region 中 MemStore 进行的,HBASE-10201/HBASE-3149引入了对 Flush 策略进行选择的功能(hbase.regionserver.flush.policy
),可以仅对超过阈值(hbase.hregion.percolumnfamilyflush.size.lower.bound.min
)的 MemStore 进行 Flush 操作。但是如果没有 MemStore 大于这个阈值,还是会对所有的 MemStore 进行 Flush 操作。
此外,如果我们的列族数过多,这可能会导致触发 RegionServer 级别的 Flush 操作;这将会导致落在该 RegionServer上的更新操作被阻塞,而且阻塞时间可能会达到分钟级别。
列族数对 Split 的影响
我们知道,当 HBase 表中某个 Region 过大(比如大于 hbase.hregion.max.filesize
配置的大小。当然,Region 分裂并不是说整个 Region 大小加起来大于 hbase.hregion.max.filesize
就拆分,而是说 Region 中某个最大的 Store/HFile/storeFile 大于 hbase.hregion.max.filesize
才会触发 Region 拆分的),会被拆分成两个。如果我们有很多个列族,而这些列族之间的数据量相差悬殊,比如有些列族有 100W 行,而有些列族只有10行,这样在 Region Split 的时候会导致原本数据量很小的 HFile 文件进一步被拆分,从而产生更多的小文件。注意,Region Split 是针对所有的列族进行的,这样做的目的是同一行的数据即使在 Split 后也是存在同一个 Region 的。
列族数对 Compaction 的影响
与 Flush 操作一样,目前 HBase 的 Compaction 操作也是 Region 级别的,过多的列族也会产生不必要的 IO。
列族数对 HDFS 的影响
我们知道,HDFS 其实对一个目录下的文件数有限制的(dfs.namenode.fs-limits.max-directory-items
)。如果我们有 N 个列族,M 个 Region,那么我们持久化到 HDFS 至少会产生 N*M 个文件;而每个列族对应底层的 HFile 文件往往不止一个,我们假设为 K 个,那么最终表在 HDFS 目录下的文件数将是 N*M*K,这可能会操作 HDFS 的限制。
列族数对 RegionServer 内存的影响
前面说了,一个列族在 RegionServer 中对应于一个 MemStore。而 HBase 从 0.90.1 版本开始引入了 MSLAB(Memstore-Local Allocation Buffers,参考HBASE-3455),这个功能默认是开启的(通过hbase.hregion.memstore.mslab.enabled
),这使得每个 MemStore 在内存占用了 2MB (通过hbase.hregion.memstore.mslab.chunksize
配置)的 buffer。如果我们有很多的列族,而且一般一个 RegionServer 上会存在很多个 Region,这么算起来光 MemStore 的缓存就会占用很多的内存。要注意的是,如果没有往 MemStore 里面写数据,那么 MemStore 的 MSLAB 是不占用空间的。
关于列族数设置的建议
在设置列族之前,我们最好想想,有没有必要将不同的列放到不同的列族里面。如果没有必要最好放一个列族。如果真要设置多个列族,但是其中一些列族相对于其他列族数据量相差非常悬殊,比如1000W相比100行,是不是考虑用另外一张表来存储相对小的列族。
为什么不建议在 HBase 中使用过多的列族的更多相关文章
- 为什么不建议在hbase中使用过多的列簇
我们知道,hbase表可以设置一个至多个列簇(column families),但是为什么说越少的列簇越好呢? 官网原文: HBase currently does not do well with ...
- HBase中Memstore存在的意义以及多列族引起的问题和设计
Memstore存在的意义 HBase在WAL机制开启的情况下,不考虑块缓存,数据日志会先写入HLog,然后进入Memstore,最后持久化到HFile中.HFile是存储在hdfs上的,WAL预写日 ...
- 从HBase底层原理解析HBASE列族不能设计太多的原因?
在之前的文章<深入探讨HBASE>中,笔者详细介绍了: HBase基础知识(包括简介.表结构).系统架构.数据存储 WAL log和HBase中LSM树的应用 HBase寻址机制 mino ...
- Hbase篇--HBase中一对多和多对多的表设计
一.前述 今天分享一篇关于HBase的一对多和多对多的案例的分析. 二.具体案例 案例一.多对多 人员-角色 人员有多个角色 角色优先级 角色有多个人员 人员 删除添加角色 角 ...
- HBase中的压缩算法比较 GZIP、LZO、Zippy、Snappy [转]
网址: http://www.cnblogs.com/panfeng412/archive/2012/12/24/applications-scenario-summary-of-compressio ...
- Flink 使用(一)——从kafka中读取数据写入到HBASE中
1.前言 本文是在<如何计算实时热门商品>[1]一文上做的扩展,仅在功能上验证了利用Flink消费Kafka数据,把处理后的数据写入到HBase的流程,其具体性能未做调优.此外,文中并未就 ...
- HBase中的备份和故障恢复方法
本文将对Apache HBase可用的数据备份机制和大量数据的故障恢复/容灾机制做简要介绍. 随着HBase在重要的商业系统中应用的大量添加,很多企业须要通过对它们的HBase集群建立健壮的备份和故障 ...
- 关于hbase中的hbase-site.xml 配置详解
该文档是用Hbase默认配置文件生成的,文件源是 hbase-default.xml hbase.rootdir 这个目录是region server的共享目录,用来持久化HBase.URL需要是'完 ...
- Hbase中HMaster作用
HMaster在功能上主要负责Table表和HRegion的管理工作,具体包括: 1.管理用户对Table表的增.删.改.查操作: 2.管理HRegion服务器的负载均衡,调整HRegion分布: 3 ...
随机推荐
- [Python Web]部署完网站需要做的基本后续工作
简述 今天自己上线了一个简单的 Page,没有什么功能就是一个展示页. 但是,我发现部署完,上线后,还要弄不少东西.下面就是我记录.整理的一些上线网站基本都会用到的网站和配置. 加入统计代码 这个是必 ...
- npm用法
查看包信息npm info mongodb 查看包的最新版本npm view mongodb version 安装npm install mongodb@2.2.33 已安装的包修改版本npm ins ...
- opensuse使用zypper安装软件
安装软件(opensuse) opensuse 通过zypper可以方便的进行软件管理,类似centos的yum 软件. 命令参考 软件包操作 搜索软件 zypper search package 安 ...
- Java开发知识之Java数组
Java开发知识之Java数组 一丶数组简介 首先,不管是Java 还是 C++ 还是其它语言.都有数组. (有可能叫法不同) 数组简而言之就是存储一段连续相同数据类型的数据结构 在Java中数组可以 ...
- PE知识复习之PE的两种状态
PE知识复习之PE的两种状态 一丶熟悉PE的整体结构 从下面依次网上看.可以得出PE结构 其中DOS头有DOS头结构 也就是 IMAGE_DOS_HEADER 关于结构体的各项属性.前边已经写过了.本 ...
- 3分钟学会如何调度运营海量Redis系统
本文由云+社区发表 作者:冯伟源 作者:冯伟源,高级工程师,腾讯云Redis系统运维负责人.6年DBA经验,一直从事SQL优化.实例调优.数据库架构.海量数据库集群运维.运营平台建设和管理等工作.为 ...
- Kafka基础入门
1. Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作 ...
- JaveWeb学习之Servlet(一):Servlet生命周期和加载机制
原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2018-07-22/19.html 作者:夜月归途 出处:http://www.guitu ...
- DSAPI HTTP监听服务端与客户端
本文中,演示了使用DSAPI.网络相关.HTTP监听,快速建立服务端和客户端. HTTP监听服务端的作用,是监听指定计算机端口,以实现与IIS相同的解析服务,提供客户端的网页请求,当然,这不仅仅是应用 ...
- C# 利用反射动态加载dll
笔者遇到的一个问题,dll文件在客户端可以加载成功,在web端引用程序报错.解决方法:利用反射动态加载dll 头部引用加: using System.Reflection; 主要代码: Assembl ...