Phoenix - sql on hbase

上篇文章最后说Hbase原生不支持sql查询,phoenix之于Hbase,就像hive之于Hadoop,会完美的实现hbase的sql查询操作,下面我们就来了解下phoenix,它不仅支持sqlonhbase,还使得创建Hbase二级索引变得更为简单。

本文主要从 phoenix 安装使用入手,介绍下 phoenix 对二级索引的使用。

一  Phoenix 安装

 

1 安装包下载

apache-phoenix-4.14.0-cdh5.14.2-bin.tar.gz

 

PS: 如果官网下载比较慢可去文末关注下载。

 

2  修改配置

 

将下载好的压缩包解压后,将phoenix目录下的 phoenix-4.8.2-HBase-1.2-server.jar、phoenix-core-4.8.2-HBase-1.2.jar 拷贝到各个 HBase 节点的 lib 目录下。

 

scp phoenix-4.14.0-cdh5.14.2-server.jar phoenix-core-4.14.0-cdh5.14.2.jar hbase01:/hbase-1.2.0-cdh5.14.2/lib/ 

scp phoenix-4.14.0-cdh5.14.2-server.jar phoenix-core-4.14.0-cdh5.14.2.jar hbase02:/hbase-1.2.0-cdh5.14.2/lib/

scp phoenix-4.14.0-cdh5.14.2-server.jar phoenix-core-4.14.0-cdh5.14.2.jar hbase03:/hbase-1.2.0-cdh5.14.2/lib/

之后将HBase的配置文件 hbase-site.xml 、 hadoop下的配置文件core-site.xml 、hdfs-site.xml 放到phoenix/bin/下,替换 phoenix 原来的配置文件。

 

cp /hadoop-2.6.0-cdh5.14.2/etc/hadoop/core-site.xml  /apache-phoenix-4.14.0-cdh5.14.2-bin/bin/

cp /hadoop-2.6.0-cdh5.14.2/etc/hadoop/hdfs-site.xml  /apache-phoenix-4.14.0-cdh5.14.2-bin/bin/

cp /hbase-1.2.0-cdh5.14.2/conf/hbase-site.xml  /apache-phoenix-4.14.0-cdh5.14.2-bin/bin/

 

记住以上配置完成后,还要重启hbase集群,使 Phoenix的 jar 包生效。

 

3 验证 phoenix 是否安装成功

 

在phoenix/bin下输入命令, 进入到命令行,接下来就可以操作了

 

bin/sqlline.py hbase01:2181

 

2181 一般是 zookeeper 的端口号,所以运行 phoenix 当然要保持 zk 、hbase、hadoop 集群为启动状态。


二  phoenix 牛刀小试

 

phoenix 使用主要分为 批处理方式、命令行方式、JDBC调用等。这里主要看下前两种。

 

  • 批处理方式

 

1.在 hbase01 上创建 phoenix.sql 文件,内容如下:

 

create table if not exists phoenix 
(state varchar(10) NOT NULL,  city varchar(20) NOT NULL,  population BIGINT  CONSTRAINT my_pk 
PRIMARY KEY (state, city));

 

2.在 hbase02 执行以下创建 phoenix.csv 文件:

 

NY,New York,8143197CA,
Los Angeles,3844829IL,
Chicago,2842518TX,
Houston,2016582PA,
Philadelphia,1463281AZ,
Phoenix,1461575TX,
San Antonio,1256509CA,
San Diego,1255540TX,
Dallas,1213825CA,
San Jose,912332

3.创建 phoenix_query.sql ,内容如下,执行 sql 语句查询:

 

select state as "userState",count(city) as "City Count",sum(population) as "Population Sum" 
from user_phoenix GROUP BY state; 

4.执行 sql 语句,查询结果:

 

apache-phoenix-4.14.0-cdh5.14.2-bin/bin/psql.py  hbase01:2181 phoenix.sql phoenix.csv phoenix_query.sql

  •  命令行方式

 

使用需要建立映射表:

1 进入 hbase 客户端,创建一个普通表 student,列族为 'school','family'

 

create 'student','school','family'

 

2. 插入数据:

 

put 'student','row1','school:name','ted'
put 'student','row1','school:adress','beijing'
put 'student','row1','family:tel','123456'
put 'student','row2','school:name','michael'
put 'student','row2','school:adress','shanghai'
put 'student','row2','family:tel','654321'

 

3.建立hbase到phoenix的映射表:

进入客户端:

 

bin/sqlline.py hbase01:2181

 

执行 sql 语句

 

 CREATE TABLE IF NOT EXISTS "student"  
("no" VARCHAR(10) NOT NULL PRIMARY KEY,  "school"."name" VARCHAR(30),"school"."address" VARCHAR(20),  "family"."tel" VARCHAR(20), "family"."age" INTEGER)  
column_encoded_bytes=0;

注意:

pheonix 是大小写敏感的,如果需要不加引号,则创建的字段或者表名都会是大写,当需要创建小写时,注意要添加引号。

 

4. 查询结果即可:

 

select * from "student";


 

三 Phoenix 构建二级索引

 

1 为什么需要二级索引?

 

对于 Hbase 而言,精确查询 使用 rowkey 就可以满足了,但是有一些场景查询需要从多个角度查询,比如查询某个人的时候需要从姓名、地址、年龄等多个维度查询,不用 rowkey 只能进行全表扫描,而大数据量情况下,全表扫描的效率是不可接受的。

所以需要建立二级索引,将业务需要的数据联立建立索引,方便查询,但是如果用 hbase 维护的话会很麻烦,这里 phoenix 已经实现了对二级索引的支持。

 

2  二级索引分类

 

二级索引有两种分法:

 

按范围分,可分为 全局索引和本地索引:

 

  • 全局索引:适用于读多写少的场景。

全局索引顾名思义,是所有表的索引,所以它的写效率很低,开销很大,因为要更新索引表,而索引表是分布在不同节点上的,跨节点数据传输会消耗较大性能。

默认情况下,pheonix 在查询时会选择索引表来提升查询效率,但是如果查询字段没在索引表中则不会使用索引查询。

 

  • 本地索引:适用于写操作频繁场景

本地索引是将索引数据与表数据放在同一节点,这样避免了跨机器写数据带来的额外开销,与全局索引不同的是,在使用本地索引时即使查询的字段不在索引表中,也会使用索引表。

一个数据表的所有索引数据都存在一个共享且独立的表中。

 

按可变性分,可分为可变索引和不可变索引:

 

  • 可变索引:适用于数据有增删改的场景

phoenix 在创建索引时默认都是可变索引,如果创建不可变索引则需要手动指定 IMMUTABLE_ROWS = true。 可变索引也分为 全局索引和 本地索引。

 

  • 不可变索引:适用于数据只增不减的情况,如日志数据。

创建不可边索引需要手动指定 IMMUTABLE_ROWS = true。不可变索引也分为 全局索引和 本地索引。

 

3 启动二级索引

 

启用二级索引需要修改 hbase 的 habse-site.xml 配置文件,添加如下配置,直接复制即可,无需改动:

 

<property>  
     <name>hbase.regionserver.wal.codec</name>  
     <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>

<property>   
     <name>hbase.region.server.rpc.scheduler.factory.class</name>   
     <value>org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory</value>
</property>

<property>    
     <name>hbase.rpc.controllerfactory.class</name>    
     <value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value>
</property>

 

注意:修改配置文件后,需要重启 hbase 集群

 

4 二级索引使用

 

这里对于索引的测试由于比较简单,我单独放在一个小文档中,有兴趣的可以去文末关注下载。

 

思考个问题:如何确保 query 查询使用 Index 呢?

 

想要让一个查询使用索引,有三种方式可以实现:

 

  • 创建转换索引:

 

如果查询项或者查询条件中包含除被索引列之外的列(主键MY_PK除外)。默认情况下,该查询会触发full table scan(全表扫描),但是使用转换索引则可以避免全表扫描。

创建包含某个字段的覆盖索引,创建方式如下:

 

create index USER_COOKIE_ID_AGE_INDEX on USER ("f"."cookie_id") include("f"."age");

 

查看当前所有表会发现多一张USER_COOKIE_ID_AGE_INDEX索引表,查询该表数据。

 

-- 如下会使用索引,转化索引包含了 age cookie_id --

select "age" from userwhere  "cookie_id"='99738fd1-2084-44e9';

-- 如下不会使用索引,索引不包含 sex --

select "age","sex" from user where  "cookie_id"='99738fd1-2084-44e9';


  • 在查询中提示使用索引

 

select /*+ index(user,USER_COOKIE_ID_AGE_INDEX) */ "age" from user where "cookie_id"='99738fd1-2084-44e9';

 

在select和column_name之间加上/*+ Index(<表名> <index名>)*/,通过这种方式强制使用索引。

 

select /*+ index(user,USER_COOKIE_ID_AGE_INDEX) */ "age" 
from user where "cookie_id"='99738fd1-2084-44e9';

-- 如下不会使用索引,索引不包含 sex --

select "age","sex" from user where  "cookie_id"='99738fd1-2084-44e9';

 

如果sex不是索引字段,那么将会进行全表扫描,所以当用户明确知道表中数据较少且符合检索条件时才适用,此时的性能才是最佳的。

 

  • 使用本地索引

 

1 创建本地索引,索引列为 “user_id”

 

create local index USER_USER_ID_INDEX on USER ("f"."user_id");

 

2 执行查询:

 

select * from user where "user_id"='371e963d-c-487065';

 

可以看到,对名为user_id的列进行按值查询需要0.3秒左右。

 

使用 EXPLAIN(语句的执行逻辑及计划):

 

 explain select * from user where "user_id"='371e963d-c-487065';

 

查看执行计划,没有执行全表扫描,使用索引,效率变高了。

 


 

索引其他命令:

 

索引重建,索引重建是把索引表清空后重新装配数据,命令如下:

 

alter index USER_COOKIE_ID_INDEX on user rebuild;

删除索引,命令如下:

 

-- 语法  drop index 索引名称 on 表名 --

drop index USER_COOKIE_ID_INDEX on user;

 

 


 

 

参考资料:关注公众号"大数据江湖", 后台回复 "phoenix",可领取文中资料,测试数据。

 

 

-- THE END --

 

select /*+ index(user,USER_COOKIE_ID_AGE_INDEX) */ "age" 
from user where "cookie_id"='99738fd1-2084-

-- 如下不会使用索引,索引不包含 sex --

select "age","sex" from user where  "cookie_id"='99738fd1-2084-44e9';
posted @ 2020-06-08 22:53  大数据江湖  阅读(277)  评论(0编辑  收藏  举报