数据预分区
主要针对初建表时只有一个region,如果写入的数据量比较大就会导致所在的region server不堪重负,写入性能低下。
create 'test', {NAME => 'cf', COMPRESSION => 'SNAPPY'}, SPLITS => ['10','20','30']
Rowkey设计
-
明确查询条件
Hbase基本可以看成一个keyvalue数据库,其中的数据需要通过key来查找,因此需要把查询条件拼接成key,将必需的条件放在前面,其他的放在后面。
-
热点问题
所有的方法都会改变原始数据的存储顺序,因此需要针对不同的场景采取适合于查询的方法。
主要有3个方法来避免热点现象,分别是反转,加盐和哈希。
- 反转: 把固定长度或者数字格式的 rowkey进行反转,反转分为一般数据反转和时间戳反转,其中以时间戳反转较常见。 缺点: 利于Get操作,但不利于Scan操作,因为数据在原RowKey上的自然顺序已经被打乱。 比如需要保存一个用户的操作记录,就可以按照操作时间倒序排序,在设计rowkey的时候,可以这样设计 反转后的userId,在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow 是 反转后的userId,stopRow 是 反转后的userId。如果需要查询某段时间的操作记录,startRow 是[反转后的userId[Long.Max_Value - 起始时间], stopRow 是反转后的userId。
- 加盐: 在原RowKey的前面添加固定长度的随机数,也就是给RowKey分配一个随机前缀使它和之前的RowKey的开头不同
- 哈希: 基于RowKey的完整或部分数据进行Hash,而后将哈希后的值完整替换或部分替换原RowKey的前缀部分。 与加盐相似只不过不是随机数,而是可以预知的一个数
代码优化
-
批量读取/写入
-
get时可传List,减少rpc调用的次数。
-
scan时可加大cache数(默认为100),使每次rpc操作取回更多的数据。
scan.setCaching(500) -
-
只取需要的列
在列较多的情况下使用
QualifierFilter,减少传回客户端的数据量。
磁盘占用
- Rowkey、列族名称和列名称在满足需求的情况下尽量短一点,因为每个cell都包含这些信息,在数据量大的情况下可以显著节省磁盘空间。
- 建表时采用snappy压缩