# HBase 和 Schema 设计
> 贡献者:[Raymondcode](https://github.com/raymondcode)
关于各种非 RDBMS 数据存储建模的优缺点,可以在 Ian Varley 的硕士论文 [No Relation: The Mixed Blessings of Non-Relational Databases](http://ianvarley.com/UT/MR/Varley_MastersReport_Full_2009-08-07.pdf) 中找到。虽然有点过时,但是如果你想了解 HBase schema 的建模方式和 RDBMS 的实现方式有什么区别的话,可以当做背景知识阅读一下。另外,阅读 [keyvalue](#keyvalue) 来了解 HBase 内部是如何存储数据的,以及 [schema.casestudies](#schema.casestudies) 章节。
Cloud Bigtable 网站上的 [Designing Your Schema](https://cloud.google.com/bigtable/docs/schema-design) 是很好的相关文档,从里面学到的内容同样适用于 HBase 领域;只要把文档里任何引用的值除 10 左右即可得到对 HBase 适用的值。比如:文档中提到单个值的大小可以到约 10MBs,HBase 也类似,或者最好尽可能的小一些;同时文档中提到,Cloud Bigtable 最多有 100 个列族,在 HBase 建模时考虑改为 约 10 个列族。
另请参阅 Robert Yokota 的 [HBase Application Archetypes](https://blogs.apache.org/hbase/entry/hbase-application-archetypes-redux) (其他 HBaser 所完成工作的最新信息),以便对 HBase 模型上的使用案例进行有用的分类。
## 34\. Schema 创建
HBase schemas 可以通过 [The Apache HBase Shell](#shell) 或者 Java API [Admin](https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/Admin.html) 来创建或者更新。
当进行列族的修改时,必须禁用表,比如:
```
Configuration config = HBaseConfiguration.create();
Admin admin = new Admin(conf);
TableName table = TableName.valueOf("myTable");
admin.disableTable(table);
HColumnDescriptor cf1 = ...;
admin.addColumn(table, cf1); // adding new ColumnFamily
HColumnDescriptor cf2 = ...;
admin.modifyColumn(table, cf2); // modifying existing ColumnFamily
admin.enableTable(table);
```
阅读 [client dependencies](#client_dependencies) 获取关于配置客户端连接的更多信息。
> 0.92.x 可以支持在线 scheme 变更, 但是 0.90.x 版本需要禁用表。
### 34.1\. Schema 更新
当表或者列族被修改时(比如 region 大小,block 大小),这些更改会在下一次 major 合并时生效,同时 StoreFiles 会被重写。
阅读 [store](#store) 获取更多关于 StoreFiles 的信息。
## 35\. 表 Schema 的经验法则
因为存在许多种不同的数据集,不同的访问模式和服务层级的要求。所以,以下经验法则只是概述。阅读完此列表后,请阅读这一章的剩余部分以获得更多详细信息。
* 目标是把 region 的大小限制在 10 到 50 GB 之间。
* 目标是限制 cell 的大小在 10 MB 之内,如果使用的是 [mob](#hbase_mob) 类型,限制在 50 MB 之内。否则,考虑把 cell 的数据存储在 HDFS 中,并在 HBase 中存储指向该数据的指针。
* 典型的 scheme 每张表包含 1 到 3 个列族。HBase 表设计不应当和 RDBMS 表设计类似。
* 对于拥有 1 或 2 个列族的表来说,50-100 个 region 是比较合适的。请记住, region 是列族的连续段。
* 保持列族名称尽可能短。每个值都会存储列族的名称(忽略前缀编码)。它们不应该像典型 RDBMS 那样,是自文档化,描述性的名称。
* 如果你正在存储基于时间的机器数据或者日志信息,并且 row key 是基于设备 ID 或者服务 ID + 时间,最终会出现这样一种情况,即更旧的数据 region 永远不会有额外写入。在这种情况下,最终会存在少量的活动 region 和大量不会再有新写入的 region。对于这种情况,可以接受更多的 region 数量,因为资源的消耗只取决于活动 region。
* 如果只有一个列族会频繁写,那么只让这个列族占用内存。当分配资源的时候注意写入模式。
- HBase™ 中文参考指南 3.0
- Preface
- Getting Started
- Apache HBase Configuration
- Upgrading
- The Apache HBase Shell
- Data Model
- HBase and Schema Design
- RegionServer Sizing Rules of Thumb
- HBase and MapReduce
- Securing Apache HBase
- Architecture
- In-memory Compaction
- Backup and Restore
- Synchronous Replication
- Apache HBase APIs
- Apache HBase External APIs
- Thrift API and Filter Language
- HBase and Spark
- Apache HBase Coprocessors
- Apache HBase Performance Tuning
- Troubleshooting and Debugging Apache HBase
- Apache HBase Case Studies
- Apache HBase Operational Management
- Building and Developing Apache HBase
- Unit Testing HBase Applications
- Protobuf in HBase
- Procedure Framework (Pv2): HBASE-12439
- AMv2 Description for Devs
- ZooKeeper
- Community
- Appendix