# Hbase的SQL中间层——Phoenix
## 一、Phoenix简介
`Phoenix`是HBase的开源SQL中间层,它允许你使用标准JDBC的方式来操作HBase上的数据。在`Phoenix`之前,如果你要访问HBase,只能调用它的Java API,但相比于使用一行SQL就能实现数据查询,HBase的API还是过于复杂。`Phoenix`的理念是`we put sql SQL back in NOSQL`,即你可以使用标准的SQL就能完成对HBase上数据的操作。同时这也意味着你可以通过集成`Spring Data JPA`或`Mybatis`等常用的持久层框架来操作HBase。
其次`Phoenix`的性能表现也非常优异,`Phoenix`查询引擎会将SQL查询转换为一个或多个HBase Scan,通过并行执行来生成标准的JDBC结果集。它通过直接使用HBase API以及协处理器和自定义过滤器,可以为小型数据查询提供毫秒级的性能,为千万行数据的查询提供秒级的性能。同时Phoenix还拥有二级索引等HBase不具备的特性,因为以上的优点,所以`Phoenix`成为了HBase最优秀的SQL中间层。
## 二、Phoenix安装
> 我们可以按照官方安装说明进行安装,官方说明如下:
>
> - download and expand our installation tar
> - copy the phoenix server jar that is compatible with your HBase installation into the lib directory of every region server
> - restart the region servers
> - add the phoenix client jar to the classpath of your HBase client
> - download and setup SQuirrel as your SQL client so you can issue adhoc SQL against your HBase cluster
### 2.1 下载并解压
官方针对Apache版本和CDH版本的HBase均提供了安装包,按需下载即可。官方下载地址: http://phoenix.apache.org/download.html
```shell
# 下载
wget http://mirror.bit.edu.cn/apache/phoenix/apache-phoenix-4.14.0-cdh5.14.2/bin/apache-phoenix-4.14.0-cdh5.14.2-bin.tar.gz
# 解压
tar tar apache-phoenix-4.14.0-cdh5.14.2-bin.tar.gz
```
### 2.2 拷贝Jar包
按照官方文档的说明,需要将`phoenix server jar`添加到所有`Region Servers`的安装目录的`lib`目录下。
这里由于我搭建的是HBase伪集群,所以只需要拷贝到当前机器的HBase的lib目录下。如果是真实集群,则使用scp命令分发到所有`Region Servers`机器上。
```shell
cp /usr/app/apache-phoenix-4.14.0-cdh5.14.2-bin/phoenix-4.14.0-cdh5.14.2-server.jar /usr/app/hbase-1.2.0-cdh5.15.2/lib
```
### 2.3 重启 Region Servers
```shell
# 停止Hbase
stop-hbase.sh
# 启动Hbase
start-hbase.sh
```
### 2.4 启动Phoenix
在Phoenix解压目录下的`bin`目录下执行如下命令,需要指定Zookeeper的地址:
+ 如果HBase采用Standalone模式或者伪集群模式搭建,则默认采用内置的 Zookeeper服务,端口为2181;
+ 如果是HBase是集群模式并采用外置的Zookeeper集群,则按照自己的实际情况进行指定。
```shell
# ./sqlline.py hadoop001:2181
```
### 2.5 启动结果
启动后则进入了Phoenix交互式SQL命令行,可以使用`!table`或`!tables`查看当前所有表的信息
## 三、Phoenix 简单使用
### 3.1 创建表
```sql
CREATE TABLE IF NOT EXISTS us_population (
state CHAR(2) NOT NULL,
city VARCHAR NOT NULL,
population BIGINT
CONSTRAINT my_pk PRIMARY KEY (state, city));
```
新建的表会按照特定的规则转换为HBase上的表,关于表的信息,可以通过Hbase Web UI 进行查看:
### 3.2 插入数据
Phoenix 中插入数据采用的是`UPSERT`而不是`INSERT`,因为Phoenix并没有更新操作,插入相同主键的数据就视为更新,所以`UPSERT`就相当于`UPDATE`+`INSERT`
```shell
UPSERT INTO us_population VALUES('NY','New York',8143197);
UPSERT INTO us_population VALUES('CA','Los Angeles',3844829);
UPSERT INTO us_population VALUES('IL','Chicago',2842518);
UPSERT INTO us_population VALUES('TX','Houston',2016582);
UPSERT INTO us_population VALUES('PA','Philadelphia',1463281);
UPSERT INTO us_population VALUES('AZ','Phoenix',1461575);
UPSERT INTO us_population VALUES('TX','San Antonio',1256509);
UPSERT INTO us_population VALUES('CA','San Diego',1255540);
UPSERT INTO us_population VALUES('TX','Dallas',1213825);
UPSERT INTO us_population VALUES('CA','San Jose',912332);
```
### 3.3 修改数据
```sql
-- 插入主键相同的数据就视为更新
UPSERT INTO us_population VALUES('NY','New York',999999);
```
### 3.4 删除数据
```sql
DELETE FROM us_population WHERE city='Dallas';
```
### 3.5 查询数据
```sql
SELECT state as "州",count(city) as "市",sum(population) as "热度"
FROM us_population
GROUP BY state
ORDER BY sum(population) DESC;
```