Phoenix 构建在 HBase 之上的开源 SQL 层. 能够让我们使用标准的 JDBC API 去建表, 插入数据和查询 HBase 中的数据, 从而可以避免使用 HBase 的客户端 API.在我们的应用和 HBase 之间添加了 Phoenix, 并不会降低性能, 而且我们也少写了很多代码.
特点
- 将 SQl 编译为 HBase 语句进行数据的CRUD
- 扫描并行执行
- 可以进行进行聚合操作
- 完美支持 HBase 二级索引创建
- 容易集成:如Spark,Hive,Pig,Flume和Map Reduce。
1. 安装
我使用的包是phoenix-hbase-2.4.0-5.1.2-bin的版本,下载完成后,上传并配置环境变量
1.1 复制jar包
cp ${PHOENIX_HOME}/phoenix-server-hbase-2.4.0-5.1.2.jar ${HBASE_HOME}/lib
cp ${HBASE}/conf/hbase-site.xml ${PHOENIX_HOME}/bin
将phoenix-server-hbase-2.4.0-5.1.2.jar复制到主机的hbase后,需要将该jar包再分发到hbase集群的其他主机
1.2 启动 phoniex
首先启动 hadoop, zookeeper, HBase,在启动 phoniex
cd /${PHONIEX_HOME}/bin
./sqlline.py hadoop101,hadoop102,hadoop103:2181
2. 命令使用
2.1 基本命令
# 查看所有表
!tables
# 删除表
drop table us_population;
# 插入或修改记录(upsert)
upsert into us_population values('NY','NewYork',8143197);
# 查询记录
select * from us_population where state='NY';
#删除记录
delete from us_population where state='NY';
2.2 创建表
1. hbase中没有表,希望在phoneix中建表,在phoneix中使用SQL向hbase表中插入数据
-- 创建表
CREATE TABLE IF NOT EXISTS ns1.us_population (
state CHAR(2) NOT NULL,
city VARCHAR NOT NULL,
info.population BIGINT
CONSTRAINT my_pk PRIMARY KEY (state, city)) column_encoded_bytes=0;
-- 新增数据
upsert into ns1.us_population values('NY','NewYork',8143197);
upsert into ns1.us_population values('CA','Los Angeles',3844829);
upsert into ns1.us_population values('IL','Chicago',2842518);
注意:在创建表时,如果不定义列族(ns1),那么默认为0号列族!
2. hbase中已经存在student表,需要在phoneix中建表,进行映射!映射后,再执行操作!
-- 注意:由于我hbase中的表名和字段均为小写,所以在phoeinx中建表的表名和字段名都要加上双引号,否则会创建出大写的表名和字段,会与HBASE中的对应不上,导致phoniex和hbase的这两张表关联不上
-- 建表
CREATE TABLE "student" (
"id" INTEGER not null primary key desc,
"info"."age" varchar,
"info"."name" varchar,
"info"."sex" varchar
) column_encoded_bytes=0;
-- 直接查询数据,有值即表示关联上了
select * from "student"
说明:
- char类型必须添加长度限制,varchar 可以不用长度限制、
- 主键映射到 HBase 中会成为 Rowkey. 如果有多个主键(联合主键), 会把多个主键的值拼成 rowkey
- 在 Phoenix 中, 默认会把表名,字段名等自动转换成大写. 如果要使用小写, 需要把他们用双引号括起来.
2.3 phoeinx和hbase关联
2.4 二级索引
2.4.1 概念
在hbase中,查询数据时,一般都会指定rowkey,或指定rowkey的范围,那么rowkey称为一级索引,如果查询某个具体的列,hbase在高版本也支持在列上创建索引,在列上创建的索引称为二级索引,二级索引的目的在想执行查询某些列的数据时,加快效率!之前如果要创建二级索引,需要自己调用HBase的API,写起来很麻烦,如果使用Phoneix,只需要一行create index 索引名 on 表名(列) SQL,Phoneix帮助我们创建二级索引!
查看sql语句是否使用了索引:使用explain + select sql
在mysql中 type=All,代表全部扫描,没有使用上索引,那么在phoneix中如果出现了FULL SCAN ,代表没有使用上二级索引,出现了全部列扫描,如果出现RANGE SCAN OVER IDX_AGE,代表使用上了某个索引,进行了范围查询!
注意测试时不能写select *;会导致索引失效
2.4.2 使用索引
创建索引:
create index idx_age on "t3"("info"."age");
删除索引:
drop index 索引名 on 表名
2.4.3 二级索引的分类
在hbase中二级索引分为gloal(全局)和local(本地)的二级索引!不管是全局索引还是本地索引,都是为了加快查询!从作用上说,没有区别!区别在于适合的场景不同:
- gloal(全局)索引:在创建后,专门在hbase中,生成一个表,讲索引的信息存储在表中。适合多读少写的场景! 每次写操作,不仅要更新数据,还需要更新索引!
例如:数据表在rs1,索引表在rs2中,每次发送一次put请求,必须先请求rs1,在请求rs2,才能完成更新,网络开销很大,加重rs的压力! - local(本地)索引,在创建后,在表中,创建一个列族,在这个列族中保存索引的信息,适合多写少读的场景! 索引是以列族的形式在表中存储,索引和数据在一个rs上,此时频繁写操作时,只需要请求当前的regionserver!
2.4.4 配置HBASE支持二级索引
1. 添加如下配置到phoenix的hbase-site.xml中
注意是phoenix下的配置文件,而不是hbase下的
<!-- phoenix regionserver 配置参数 -->
<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>
<description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<property>
<name>hbase.rpc.controllerfactory.class</name>
<value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value>
<description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<property>
<name>hbase.master.loadbalancer.class</name>
<value>org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer</value>
</property>
<property>
<name>hbase.coprocessor.master.classes</name>
<value>org.apache.phoenix.hbase.index.master.IndexMasterObserver</value>
</property>
-- 为student表的age字段添加二级索引
create index idx_age on "student"("info"."age");
结果: