利用phoenix建立二级索引查询hbase,大神请无视

利用phoenix建立二级索引查询hbase

phoenix的简单介绍

 phoenix,中文译为“凤凰”,很美的名字。Phoenix是由saleforce.com开源的一个项目,后又捐给了Apache基金会。它相当于一个Java中间件,提供jdbc连接,操作hbase数据表。Phoenix是一个HBase的开源SQL引擎。你可以使用标准的JDBC API代替HBase客户端API来创建表,插入数据,查询你的HBase数据。Phoenix的团队用了一句话概括Phoenix:"We put the SQL back in NoSQL" 意思是:我们把SQL又放回NoSQL去了!这边说的NoSQL专指HBase,意思是可以用SQL语句来查询Hbase,你可能会说:“Hive和Impala也可以啊!”。但是Hive和Impala还可以查询文本文件,Phoenix的特点就是,它只能查Hbase,别的类型都不支持!但是也因为这种专一的态度,让Phoenix在Hbase上查询的性能超过了Hive和Impala!
 Phoenix是构建在HBase之上的SQL引擎。你也许会存在“Phoenix是否会降低HBase的效率?”或者“Phoenix效率是否很低?”这样的疑虑,事实上并不会,Phoenix通过以下方式实现了比你自己手写的方式相同或者可能是更好的性能(更不用说可以少写了很多代码):
编译你的SQL查询为原生HBase的scan语句。检测scan语句最佳的开始和结束的key。精心编排你的scan语句让他们并行执行。推送你的WHERE子句的谓词到服务端过滤器处理。执行聚合查询通过服务端钩子(称为协同处理器)。 

除此之外,Phoenix还做了一些有趣的增强功能来更多地优化性能:
实现了二级索引来提升非主键字段查询的性能。统计相关数据来提高并行化水平,并帮助选择最佳优化方案。跳过扫描过滤器来优化IN,LIKE,OR查询。优化主键的来均匀分布写压力。 
我相信,二级索引这个特性应该是大部分用户引入Phoenix主要考虑的因素之一。HBase因其历史原因只支持rowkey索引,当使用rowkey来查询数据时可以很快定位到数据位置。现实中,业务查询需求条件往往比较复杂,带有多个查询字段组合,如果用HBase查的话,只能全表扫描进行过滤,效率很低。而Phoenix支持除rowkey外的其它字段的索引创建,即二级索引,查询效率可大幅提升。

多的不说了:开搞,我是在测试环境搞的。
1、首先找到自己服务器上phoenix的安装目录,由于不是我装的,我只能locate一下:

locate phoenix

然后出来一堆目录找到跟我这个目录相似的:
/mnt/cdh/cloudera/parcels/CLABS_PHOENIX-4.7.0-1.clabs_phoenix1.3.0.p0.000/lib/phoenix

2、启动phoenix

/mnt/cdh/cloudera/parcels/CLABS_PHOENIX-4.7.0-1.clabs_phoenix1.3.0.p0.000/lib/phoenix/
bin/sqlline.py 10.1.47.14:2181 

3、启动hbase

hbase shell

4、在hbase里面创建一个表

create 'RCM_TEST2','cf1'

5、在phoenix中创建RCM_TEST2的映射表

create table if not exists "RCM_TEST2"
(
"cf1"."dateid" VARCHAR(100),
"riskid" VARCHAR(100),
"saledeptid" VARCHAR(100),
"cf1"."salechnlcode" VARCHAR(100),
"cf1"."payintvcode" VARCHAR(100),
"cf1"."paytermcode" VARCHAR(100),
"cf1"."mainriskflag" VARCHAR(100),
"cf1"."mainriskid" VARCHAR(100),
"cf1"."mainpayintvcode" VARCHAR(100),
"cf1"."mainpaytermcode" VARCHAR(100),
"cf1"."employyear" VARCHAR(100),
"cf1"."agentgradeid" VARCHAR(100),
"cf1"."agentcode" VARCHAR(100),
"cf1"."agentcomid" VARCHAR(100),
"cf1"."contplancode" VARCHAR(100),
"cf1"."inputtype" VARCHAR(100),
"cf1"."year_cardprem" VARCHAR(100),
"cf1"."year_yaddition_prem" VARCHAR(100),
"cf1"."year_resurrder_prem" VARCHAR(100),
"cf1"."year_yaddition_prem_auto" VARCHAR(100),
"cf1"."year_laddition_prem" VARCHAR(100),
"cf1"."year_addition_prem" VARCHAR(100),
"cf1"."year_health_prem" VARCHAR(100),
"cf1"."year_intiv_prem_three" VARCHAR(100),
"cf1"."year_intiv_prem_3_5" VARCHAR(100),
"cf1"."year_intiv_prem_5_9" VARCHAR(100),
"cf1"."year_intiv_prem_ten" VARCHAR(100),
"cf1"."year_intiv_prem_main" VARCHAR(100),
"cf1"."year_intiv_prem" VARCHAR(100),
"cf1"."year_valueprem" VARCHAR(100),
"cf1"."year_valueprem_resur" VARCHAR(100),
"cf1"."year_renewpol_prem" VARCHAR(100),
"cf1"."year_premium_sum" VARCHAR(100),
"cf1"."year_addition_prem_resur" VARCHAR(100),
"cf1"."year_intiv_prem_ten_resur" VARCHAR(100),
"cf1"."year_health_prem_resur" VARCHAR(100),
"cf1"."year_fi_health_prem" VARCHAR(100),
"cf1"."year_yaddition_prem_resur" VARCHAR(100),
"cf1"."year_laddition_prem_resur" VARCHAR(100),
"cf1"."year_fi_health_prem_resur" VARCHAR(100),
"cf1"."year_laddition_aseprem" VARCHAR(100),
"cf1"."year_cardrenew_prem_auto" VARCHAR(100),
"cf1"."year_cardprem_value" VARCHAR(100),
"cf1"."year_intiv_valueprem_main" VARCHAR(100),
"cf1"."year_laddition_valueprem" VARCHAR(100),
"cf1"."year_yaddition_value" VARCHAR(100),
"cf1"."year_policy_value" VARCHAR(100),
"cf1"."year_yaddition_prem_aut_value" VARCHAR(100),
"cf1"."feeopertypefalg" VARCHAR(100),
"cf1"."loaddate" VARCHAR(100)
CONSTRAINT PK PRIMARY KEY ("riskid","saledeptid"));

这里我设置了复合主键riskid,saledeptid,注意作为主键的字段建表的时候不要写列族名字。

6、为了查询更快,我们对两个主键建立二级索引。

create index "RCM_TEST2_INDEX2" on "RCM_TEST2"("riskid","saledeptid"); 

7、加载数据到hbase
利用phoenix的PSQL加载数据文件到表中,由于建立了二级索引,这种加载方式非常慢,建议编写MR程序。

/mnt/cdh/cloudera/parcels/CLABS_PHOENIX-4.7.0-1.clabs_phoenix1.3.0.p0.000/lib/phoenix/bin/psql.py -t RCM_TEST2 -d'^' 10.1.47.14:2181  /home/sma_admin/rcm2.csv

这里-d后面是自定义的分隔符,由于我的数据文件rcm2.csv里面字段的分隔符是^,
所以这里采用^符号分隔。-t后面是表名字,phoenix对大小写比较敏感,采用大写没有问题,如果必须小写,要加特殊符号。

8、数据条数查看168168条,16万多条。
在这里插入图片描述
9、简单测试

不走索引的查询,执行如下sql,耗时4.832秒:

select "saledeptid","paytermcode" from "RCM_TEST2" WHERE "mainriskid"='584';

在这里插入图片描述
我们来查看一下这个sql的执行过程,应为where后面字段没有建立二级索引,所以查询较慢,是全表sacn的。

explain select "saledeptid","paytermcode" from "RCM_TEST2" WHERE "mainriskid"='584';

在这里插入图片描述
走索引的查询,执行如下sql,耗时0.148秒:

select "saledeptid","paytermcode" from "RCM_TEST2" WHERE "riskid"='584';

在这里插入图片描述
我们来查看一下这个sql的执行过程,应为where后面字段建立二级索引,所以查询块,是通过索引进行区间scan的。

explain select "saledeptid","paytermcode" from "RCM_TEST2" WHERE "riskid"='584';

在这里插入图片描述
10、由于我么建立了两个字段,按照资料上说hbase中RCM_TEST2这个表中的rowkey应该是两个主键拼接起来,我查看了一下,没太看懂,主键如下所示。

 108\x001024                column=cf1:_0, timestamp=1577258805546, value=x
 108\x001024               column=cf1:agentcode, timestamp=1577258805546, value=23240220
 108\x001024               column=cf1:agentcomid, timestamp=1577258805546, value=0
 108\x001024               column=cf1:agentgradeid, timestamp=1577258805546, value=8
 108\x001024               column=cf1:dateid, timestamp=1577258805546, value=20190331
 108\x001024               column=cf1:employyear, timestamp=1577258805546, value=17
 108\x001024               column=cf1:feeopertypefalg, timestamp=1577258805546, value=7
 108\x001024               column=cf1:loaddate, timestamp=1577258805546, value=06/12/2019 01:01:02
 108\x001024               column=cf1:mainpayintvcode, timestamp=1577258805546, value=12
 108\x001024               column=cf1:mainpaytermcode, timestamp=1577258805546, value=20
 108\x001024               column=cf1:mainriskflag, timestamp=1577258805546, value=1
 108\x001024               column=cf1:mainriskid, timestamp=1577258805546, value=244
 108\x001024               column=cf1:payintvcode, timestamp=1577258805546, value=0
 108\x001024               column=cf1:paytermcode, timestamp=1577258805546, value=0
 108\x001024               column=cf1:salechnlcode, timestamp=1577258805546, value=1
 108\x001024               column=cf1:year_addition_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_addition_prem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_cardprem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_cardprem_value, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_fi_health_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_fi_health_prem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_health_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_health_prem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_3_5, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_5_9, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_main, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_ten, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_ten_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_prem_three, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_intiv_valueprem_main, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_laddition_aseprem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_laddition_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_laddition_prem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_laddition_valueprem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_policy_value, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_premium_sum, timestamp=1577258805546, value=260.00
 108\x001024               column=cf1:year_renewpol_prem, timestamp=1577258805546, value=260.00
 108\x001024               column=cf1:year_resurrder_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_valueprem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_valueprem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_yaddition_prem, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_yaddition_prem_aut_value, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_yaddition_prem_auto, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_yaddition_prem_resur, timestamp=1577258805546, value=0.00
 108\x001024               column=cf1:year_yaddition_value, timestamp=1577258805546, value=0.00

如上是一条完整数据,rowke是108\x001024 ,这个是什么意思?看懂的人评论一下。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值