Phoenix - sql on hbase
上篇文章最后说Hbase原生不支持sql查询,phoenix之于Hbase,就像hive之于Hadoop,会完美的实现hbase的sql查询操作,下面我们就来了解下phoenix,它不仅支持sqlonhbase,还使得创建Hbase二级索引变得更为简单。
本文主要从 phoenix 安装使用入手,介绍下 phoenix 对二级索引的使用。
一 Phoenix 安装
1 安装包下载
- 从对应的地址下载:http://archive.apache.org/dist/phoenix/ 下载时注意版本兼容问题,这里我使用的是
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';