0、设计理念
(1)解决HBase不支持创建索引、不支持聚合函数的问题
(2)Phoenix是架构在HBase上的JDBC工具,使用HBase的API和SQL语句对HBase表进行增删改查
(3)使用比Hive快很多,兼具了HBase的快速、SQL语句和聚合函数
1、安装配置
(1)tar -zxvf apache-phoenix-4.10.0-HBase-1.2-bin.tar.gz -C /soft ====== 解压到指定目录
(2)ln -s apache-phoenix-4.10.0-HBase-1.2-bin.tar.gz phoenix ====== 创建符号链接
(3)sudo nano /etc/profile ====== 配置环境变量,添加以下内容:
# phoenix环境变量
export PHOENIX_HOME=/soft/phoenix
export PATH=$PATH:$PHOENIX_HOME/bin
(4)source /etc/profile ====== 生效环境变量
(5)cp /soft/phoenix/phoenix-4.10.0-HBase-1.2-client.jar /soft/hbase/lib/ ====== 拷贝客户端jar包
(6)xsync.sh /soft/hbase/lib/phoenix-4.10.0-HBase-1.2-client.jar ====== 将客户端jar包分发到其他节点
(7)nano /soft/phoenix/bin/hbase-site.xml,添加以下内容:
phoenix.schema.isNamespaceMappingEnabled
true
(8)nano /soft/hbase/conf/hbase-site.xml,添加以下内容:
phoenix.schema.isNamespaceMappingEnabled
true
(9)xsync.sh /soft/hbase/conf/hbase-site.xml ====== 分发配置文件
(10)依次启动ZooKeeper,Hadoop,HBase
(11)sqlline.py s102,s103,s104 ====== 启动Phoenix,尾随ZK地址,会初始化原数据到HBase
2、使用命令
help ====== 查看帮助
!tables ====== 查看当前的表
select * from system.catalog; ====== 查询表数据(必须指定SCHEMA)
create table "users"(id integer primary key); ====== 建表(必须指定主键,映射到HBase表中的rowkey),不加双引号默认是大写,加上是小写
upsert into users values(10); ====== 插入数据
alter table users add name varchar; ====== 添加字段
upsert into users(id,name) values(10,'toms'); ====== 修改某个字段的值
delete from users where id=10; ====== 删除数据
select avg(age) from users; ====== 使用聚合函数
3、深究语法
select * from users limit 2 offset 1; ====== 从偏移量1开始查询两条数据(第一条数据的偏移量是0)
upsert into users(id,name,age) values(40,'ma',50); ====== 表中已存该key时覆盖表中的数据
upsert into users(id,name,age) values(40,'ma',50) on duplicate key ignore; ====== 表中已存该key时忽略本次插入
delete from users where name like 'tom%'; ====== 模糊匹配,%表示零个或多个字符
create table ns1.t1(id unsigned_int primary key, name varchar, age unsigned_int); ====== 指定SCHEMA建表,映射在HBase中是"NS1.T1"
create table if not exists "maliuc"( "id" varchar not null primary key, "value" integer) versions=5 split on ('a','b','c'); ====== 指定版本数和分区标记建表
create table if not exists "YEMA" ("ID" varchar not null primary key, "VALUE" integer) versions=5 split on ('a','b','c'); ====== 建表,必须加引号,引号内大写即为大写
create table if not exists "yema" ("id" varchar not null primary key, "value" integer) versions=5 split on ('a','b','c'); ====== 建表,必须加引号,引号内小写即为小写
create view myview as select * from users where age<30; ====== 创建视图,本身(在HBase中)不存在,仅仅是SQL语句,不能隐藏字段
drop view myview; ====== 删除视图
explain select * from myview; ====== 解析SQL语句采用哪种扫描方式
create schema myschema; ====== 创建schema,映射到hbase的namespace(需修改phoenix和hbase的hbase-site.xml,并分发hbase的hbase-site.xml)
4、JDBC编程
(1)create table customers(id unsigned_int primary key, name varchar, age unsigned_int); ====== 建表
(2)修改pom.xml文件
org.apache.phoenix
phoenix-core
4.10.0-HBase-1.2
junit
junit
4.12
(3)在resource中添加hbase-site.xml文件
phoenix.schema.isNamespaceMappingEnabled
true
(4)编写插入数据的代码
public void testInsert() throws Exception {
Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
String url = "jdbc:phoenix:s102,s103,s104";
Connection conn = DriverManager.getConnection(url);
PreparedStatement ps = conn.prepareStatement("upsert into customers values (?, ?, ?)");
for (int i = 1; i < 100; i++) {
ps.setInt(1,i);
ps.setString(2,"tom" + i);
ps.setInt(3,i % 80);
ps.execute();
}
conn.commit();
ps.close();
conn.close();
}
(5)编写查询数据的代码
public void testSelect() throws Exception {
Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
String url = "jdbc:phoenix:s102,s103,s104";
Connection conn = DriverManager.getConnection(url);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from customers");
while(rs.next()){
int id = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
System.out.println(id + "/" + name + "/" + age);
}
rs.close();
st.close();
conn.close();
}
5、HBase和Phoenix表的映射
(1)在HBase中建表(不能加名字空间)
create 'wc', 'f1', 'f2'
(2)往HBase表中插入数据
put 'wc', 'row1', 'f1:name', 'toms'
put 'wc', 'row2', 'f1:name', 'tony'
put 'wc', 'row1', 'f1:age', '20'
put 'wc', 'row2', 'f1:age', '30'
(3)在Phoenix中建表并映射(不能加schema)
create table "wc"(id varchar primary key, "f1"."name" varchar, "f1"."age" varchar);
(4)查询Phoenix表是否映射成功
select * from "wc";
(5)在Phoenix表中插入数据
upsert into "wc" values('row3', 'yema', '23');
(6)查询HBase表是否映射成功
scan 'wc'
6、索引(提高查询效率)
(0)作用:额外维护一个表,将相应字段组合成一个rowkey,在查询的时候,先搜索索引的相应字段;索引是实时更新的(仅限于Phoenix插入,HBase插入不会触发更新,若想更新需要rebuild)
alter index index_wc on "wc" rebuild;
(1)要在Phoenix中使用索引,必须配置HBase的hbase-site.xml文件
(1-1)nano /soft/hbase/conf/hbase-site.xml,添加以下内容:
hbase.regionserver.wal.codec
org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec
(1-2) xsync.sh /soft/hbase/conf/hbase-site.xml ====== 分发配置文件
(2)create index index_wc on "wc"(id, "f1"."name", "f1"."age"); ====== 创建二级索引,额外维护一个表
7、函数
(0)Phoenix支持转储,但不支持"ctas"语句
upsert into wcc select * from "wc";
(1)select avg(age) from customers;
(2)select first_value(name) within group (order by age desc) from customers; ====== 求年龄最大的人的名字
(3)select substr('helloworld',5); ====== 从第5个开始查询(以1开始,不是0)
(4)select substr('helloworld',-1); ====== 从倒数第一个开始查询
(5)select substr('helloworld',1,3); ====== 从第一个开始,查询三个
(6)select regexp_split('hello world', ' '); ====== 以空格截串
(7)select array_elem(regexp_split('hello world', ' '), 1); ====== 查询截串后的第一个元素
(8)日期函数
select to_date('2018-02-02 03:09:09', 'yyyy-MM-dd hh:mm:ss'); //date类型
select TO_TIME('2018-02-02 03:09:09', 'yyyy-MM-dd hh:mm:ss'); //time类型
select YEAR(TO_DATE('2015-6-05'));
select MONTH(TO_DATE('2015-6-05'));
select WEEK(TO_DATE('2015-6-05'));
select DAYOFYEAR(TO_DATE('2015-6-05'));
select HOUR(TO_DATE('2015-6-05'));
select MINUTE(TO_DATE('2015-6-05'));
select SECOND(TO_DATE('2015-6-05'));