hbase环境配置优化:
几个配置参数:
hbase.hregion.max.filesize:
1)当hbase.hregion.max.filesize比较小时,触发split的机率更大,而split的时候会将regionoffline,因此在split结束的时间前,访问该region的请求将被block住,客户端自我block的时间默认为1s。当大量的region同时发生split时,系统的整体访问服务将大受影响。因此容易出现吞吐量及响应时间的不稳定现象
2)当hbase.hregion.max.filesize比较大时,单个region中触发split的机率较小,大量region同时触发split的机率也较小,但是由于长期得不到split,因此同一个region内发生多次compaction的机会增加了。compaction的原理是将原有数据读一遍并重写一遍到hdfs上,然后再删除原有数据。无疑这种行为会降低以io为瓶颈的系统的速度,因此平均吞吐量会受到一些影响而下降。
综合以上两种情况,hbase.hregion.max.filesize不宜过大或过小,调大该值可以减少region的数量,调到2G不为过。
hbase.hregion.memstore.flush.size
hbase.hregion.memstore.flush.size意思一个region下面的所有store里面的memstore的达到多少时,开始将这些memstoreflush到hdfs中去,配置这个值,需要参考一下,平均每个regionserver管理的region数量,如果每台regionsever管理的region不多的话,可以适当的调大该值,如512M时再flush
hfile.block.cache.size
是整个堆内存的多少比例作为regionserver的cache,调大该值会提升查询性能,当然也不能过大,如果你的hbase都大量的查询,写入不是很多的话,调到0.5
hbase.regionserver.global.memstore.upperLimit
配置一台regionserver所有memstore占整个堆的最大比例; 与hfile.block.cache.size二者的和不超过1;
程序有关注意配置:
autoflush=false
提高hbase的写入速度应用代码中设置autoflush=false;但是机器崩溃可能丢数据;
table中family和qualifier
从读的方面考虑:
family越多,那么获取每一个cell数据的优势越明显
从写的角度考虑:
首先,内存方面来说,对于一个Region,会为每一个表的每一个Family分配一个Store,而每一个Store,都会分配一个MemStore,所以更多的family会消耗更多的内存。
第三,从split方面考虑,由于hfile是以family为单位的,因此对于多个family来说,数据被分散到了更多的hfile中,减小了split发生的机率。这是把双刃剑。更少的split会导致该region的体积比较大,由于balance是以region的数目而不是大小为单位来进行的,因此可能会导致balance失效。而从好的方面来说,更少的split会让系统提供更加稳定的在线服务。
Phoenix
二级索引:hbase-site.xml
需要增加才行:
hbase.regionserver.wal.codec
org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec
SALT_BUCKETS是全局索引分桶,主要是解决region热点问题,由于rowkey设计不当,很可能绝大部分的row都会落入一个region中,那么其对应index通过设置SALT_BUCKETS[1~255]来将这些index分桶存储。如果主表添加了properties,那么它的index会继承这些properties。不过,index的MAX_FILESIZE相对主表的值被降低了。
例子
CREATETABLEexample1 (k VARCHAR PRIMARY KEY, m.c0 VARCHAR, m.c1 VARCHAR,m.c2 VARCHAR)
create index idx on example(m.c0, m.c1,m.c2)
注意为多个column创建索引,在查询时要按照索引列的顺序来查询。例如,为M.C0、M.C1和M.C2建立索引:
该例子会隐式的创建(m.c0),(m.c0, m.c1),(m.c0, m.c1,m.c2)三个索引,如果在where中用这三个条件会用到索引,其他组合则无法使用索引(FULLSCAN)。
在查询时,可以同时根据将这3列作为条件,且顺序不限。但是,第一列必须是M.C0。这是因为:当为多列建立索引时,rowkey实际上是这些column的组合,并且是按照它们的先后顺序的组合。如果查询时第一列不是M.C0,那么就要进行fullscan,速度会很慢。而如果查询的第一列是M.C0,就可以直接将满足关于M.C0的数据记录找出来。即使后面还有没有被索引的列,也可以很快得到结果,因为满足关于M.C0的结果集已经不大了(如果是这种情况的话),对其再进行一次查询不会是fullscan。
查询条件中主键索引+二级索引同时存在的话,Phoenix会自己选择最优索引。
例子
创建表:
CREATETABLE TEST(pk1 char(1) not null, pk2 char(1) not null, pk3 char(1)not null, nonpkvarchar CONSTRAINT PK PRIMARY KEY(pk1, pk2,pk3));
不会使用到索引的检索:
select* from testwhere pk2='x' andpk3='y'
会使用到索引的检索:
select* from testwhere pk1='x' and pk2='y'
select* from testwhere pk3='x' and pk1='y'
select* from testwhere pk1='x' and pk3='y'
在hbase-site.xml里还可以配置以下参数
1. index.builder.threads.max
o 为主表更新操作建立索引的最大线程数
o Default:10
2. index.builder.threads.keepalivetime
o 上面线程的超时时间
o Default:60
3. index.writer.threads.max
o 将索引写到索引表的最大线程数
o Default:10
4. index.writer.threads.keepalivetime
o 上面线程的超时时间
o Default:60
5. hbase.htable.threads.max
o 同时最多有这么多线程往索引表写入数据
o Default:2,147,483,647
6. hbase.htable.threads.keepalivetime
o 上面线程的超时时间
o Default:60
7. index.tablefactory.cache.size
o 缓存10个往索引表写数据的线程
o Default:10