# 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