Row Key
- 类似于MySQL中的主键,HBase天然自带的,在创建时不需要显示指定。
- HBase不支持条件查询和Order by等查询,读取记录只有三种方式:①. 通过单个Row key访问【速度很快,因为存在着索引机制】②. 给定Row key的range ③. 全表扫描
- Row key按照字典序存储,要充分考虑排序存储这个特性,将经常一起读取的行存储放到一起(位置相关性)。设计方法参见HBase表设计
- 字典序对int排序的结果是1,10,100,11,2,20,21,…,9。要保持整形的自然序,行键必须用0作左填充。
- 行的一次读写是原子操作 (不论一次读写多少列),使得多用户不能并发对同一个行进行更新操作。
Column Family
- 建表时手动指定,包含一个或者多个列
- 列族中的数据都是以二进制的形式保存在hdfs上,没有数据类型
- 增加新的列族:先disable 'users' / alter 'users','info' / enable 'users'。
- 删除列族方式:先disable 'users' / alter 'users',{NAME=>'info',METHOD=>'delete'} / enable 'users'
- 不能重命名列族:通常做法是使用API创建一个有着期望名称的新的列族,然后将数据复制过去,最后再删除旧的列族。
- 每个列族存储在HDFS上的一个单独文件中,空值不会被保存。
- 同一Column Family的Columns会群聚在一个存储文件上,并依Column key排序,因此设计时:读写相关性较高的数据,存在同一列族中。
Column
- 列名在添加数据时动态添加,无需在建表时指定。没有具体的数据类型,以二进制方式存储在HDFS上。
- 设置列值:put 'users','xiaoming','info:age','18'
- 读取列值:get 'users','info:age'
TimeStamp
- 默认值使用系统时间戳,如果应用程序要避免数据时间戳冲突,就必须自己生成具有唯一性的时间戳。
- 每个cell中,不同版本的数据按照时间倒序排列,即最新的数据排在最前面。
- 为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,HBase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(即设置HColumnDescriptor.setTimeToLive(); 比如最近七天)。用户可以针对每个列族单独进行设置。
Cell
- HBase中通过" tableName + RowKey + ColumnKey "确定的唯一存贮单元称为Cell。
- 每个Cell都保存着同一份数据的多个版本,每个版本通过时间戳Time Stamp来索引。
- Cell的每个值通过4个键唯一索引,tableName + RowKey + ColumnKey + Timestamp => value
存储类型
- TableName 是字符串
- RowKey 和 ColumnFamily 是二进制值(Java 类型 byte[])
- Timestamp 是一个 64 位整数(Java 类型 long)
- Value 是一个字节数组(Java类型 byte[])。
HBase是一种专门为半结构化数据(semistructured)和水平可扩展性(horizontalscalability)设计的数据库。
它把数据存储在表里。在表里,数据按照一个四维坐标系统来组织:行键、列族、列限定符和时间版本。
HBase 是无模式数据库,只需要提前定义列族。它也是无类型数据库,把所有数据不加解释地按照字节数组存储。
有5个基本命令用来访问HBase中的数据,即Get、Put、Delete、Scan 和Increment。
基于非行键值查询HBase的唯一办法是通过带过滤器的扫描Scan。
HBase 不是一个ACID 兼容数据库。但是HBase 提供一些保证,当你的应用系统访问HBase系统时,你可以用其来使你的应用系统的行为更加合理。这些保证具体如下。
1.操作是低级原子不可分的。换句话说,指定行的Put()要么整体成功要么整体失败回到操作开始前的状态,永远不会部分行写入而另一部分没有。这个要素和操作执行的列族的数量无关。
2.行间操作不是原子性的。不能保证所有操作整体成功或者失败。所有单行操作如上一点所述是原子性的。
3.checkAnd*和increment*操作是原子不可分的。
4.对于给定行的多个写操作,总是以每个写操作为整体彼此独立的。这是第一点的延伸。
5.对于给定行的任何Get()操作,返回系统当时所保存的完整行。
6.全表扫描不是对某个时间点表的快照的扫描。如果扫描已经开始,但是在行R 被扫描器对象读出之前,行R 被改变了,那么扫描器读出行R 更新后的版本。但是扫描器读出的数据是一致的,得到行R 更新后的完整行。
当你搭建使用HBase 的应用系统时,这些背景信息是你需要注意的要点。
- 数据模型从逻辑上可以分类为键值存储或有序映射的映射。物理数据模型是基于列族的列式数据库,单个记录以键值形式存储。HBase 把数据记录保存在HFile里,这是一种不能更改的文件格式。因为记录一旦写入就不能修改,新值将保存在新HFile里。在读取数据和数据合并时,数据视图需要在内存中重新衔接。
- HBase Java API 通过HTableInterface 来使用表。表连接可以直接通过构造HTable 实例来建立。使用HTable 实例系统开销大,优选方式是使用HTablePool,因为它可以重复使用连接。表通过HbaseAdmin 、HTableDescriptor 和HColumnDescriptor 类的实例来新建和操作。5 个命令通过相应的命令对象来使用:Get、Put、Delete、Scan 和Increment。命令送到HtableInterface 实例来执行。递增Increment 有另外一种用法,使用HTableInterface.incrementColumnValue()方法。执行Get、Scan 和Increment 命令的结果返回到Result和ResultScanner 对象的实例。一个KeyValue 实例代表一条返回记录。所有这些操作也可以通过HBase Shell 以命令行方式执行。
- 预期的数据访问模式对HBase 的模式设计有很大的影响。理想情况下,HBase 中的表根据预期的模式来组织。行键是HBase 中唯一的全局索引坐标,因此查询经常通过行键扫描实现。复合行键是支持这种扫描的常见做法。行键值经常希望是均衡分布的。诸如MD5 或SHA1 等散列算法通常用来实现这种均衡分布。