phoenix 作为大数据生态圈中的一员得力干将,并没有大家想象中的那么神秘,它对原始的hbase 进行了封装,而hbase是列式存储数据库,可能跟传统的关系型数据还是有那么一点差异的,所以想要熟悉并初步掌握phoenix,则需要熟悉它的三板斧之功效:
第一板斧之加盐(SALT_BUCKETS)
正如前面所说的phoenix 是对hbase 进行了封装,那么hbase存在的特性预分区,也会在phoenix 中体现出来——加盐正是这种体现,那么SALT_BUCKETS具体设置多少合适呢,则需要参考三个因素:1.regionserver 个数 2.数据量 3.CPU的核数
当block cache和表的大小差不多时,SALT_BUCKETS设置成REGIONSERVER的相同大小;
当表的大小远大于block cache时,SALT_BUCKETS 可以相对设置大一些,但是要考虑CPU的情况,参考文档https://community.cloudera.com/t5/Support-Questions/How-many-salt-buckets-should-I-use-for-my-Phoenix-tables/m-p/159797
第二板斧之压缩(ompression)
phoenix目前常用的压缩方法:SNAPPY,GZ
create table order_center.tr_order_bak
( row_key varchar(64) not null primary key,
id bigint,
tenant_id varchar(64) ,
localorderid varchar(64) ,
shopid varchar(64) ,
shopcode varchar(32) ,
shopname varchar(128) ,
orderchannel varchar(32) ,
total_amount decimal(16,2)
)SALT_BUCKETS=5,compression='SNAPPY';
第三板斧之索引(index)
phoenix 中的主键跟hbase的row key 类似,如果不建索引,只有通过row key 查询效率才会高,但是在正常的使用过程中,往往会遇到复杂的查询或者计算,那么就必须要使用到索引,注意phoenix 的索引跟关系型数据库索引的不同。
mysql:b+tree索引,索引上只存储了键值和指针
phoenx:将数据重新复制了一份,然后将索引列当做rowkey的过程,所以索引必须包含查询中所有的列,否则不走索引。
create index idx_oder_orderid_shopcode_bak on order_center.tr_order_bak(tenant_id,localorderid,shopcode)
include(id,shopid,shopname,orderchannel)SALT_BUCKETS=5;
通过上面两张SQL的执行计划的对比可以看到查询语句之间只差了一个total_amount,就发生了翻天地覆的变化,在执行效率上也会天差地别的。当表中的数据已经存在数据了,但是新增了查询的业务场景怎么办呢?
create index idx_oder_orderid_shopcode_bak on order_center.tr_order_bak(tenant_id,localorderid,shopcode)
include(id,shopid,shopname,orderchannel)ASYNC;
/usr/hdp/2.6.5.0-292/hbase/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool --schema ORDER_CENTER --data-table TR_ORDER_BAK --index-table idx_oder_orderid_shopcode_bak --output-path idx_oder_orderid_shopcode_bak_HFILES
正常情况下,经过上面两步就可以了,但是当数据量非常大的时候,需要考虑服务器磁盘的使用情况,新增索引就是重新复制了一份数据,如果磁盘使用超过90%的时候,可能导致创建索引创建失败。