HBase客户端SQL引擎之Apache Phoenix的安装与使用
Apache Phoenix为Apache Hadoop 提供基于SQL的OLTP和运营分析,使用Apache HBase作为其后备存储,并提供与Apache生态系统中其他项目的集成,如Spark、Hive、Pig、Flume和MapReduce ......
目录
HBase客户端SQL引擎之Apache Phoenix的安装与使用
2 部署apache-phoenix-5.0.0-HBase-2.0
1 概述
- Phoenix最早是saleforce的一个开源项目,后来成为Apache基金的顶级项目。
- Phoenix是构建在HBase上的一个SQL层,能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表、插入数据和对HBase数据进行查询。
- Phoenix完全使用Java编写,作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫描,并编排执行以生成标准的JDBC结果集。
- 直接使用HBase API、协同处理器与自定义过滤器,对于简单查询来说,其性能量级是毫秒,对于百万级别的行数来说,其性能量级是秒。
- 下载的Phoenix版本必须和hbase目标版本保持一致。
2 部署apache-phoenix-5.0.0-HBase-2.0
-
下载及解压 (hd100上执行)
[root@hd100 ~]# cd /opt/src/
[root@hd100 src]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/phoenix/apache-phoenix-5.0.0-HBase-2.0/bin/apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz
...
[root@hd100 src]# ls -l apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz
-rw-r--r-- 1 root root 436868323 11月 12 14:47 apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz
[root@hd100 src]# tar -zxvf apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz
...
[root@hd100 src]# mv apache-phoenix-5.0.0-HBase-2.0-bin /home/hadoop/phoenix-5.0.0-HBase-2.0
[root@hd100 src]# cd /home/hadoop/phoenix-5.0.0-HBase-2.0
-
vi /home/hadoop/hbase/conf/hbase-site.xml #增加以下内容
<property>
<name>phoenix.schema.isNamespaceMappingEnabled</name>
<value>true</value>
</property>
<property>
<name>phoenix.schema.mapSystemTablesToNamespace</name>
<value>true</value>
</property>
-
拷贝hbase和hadoop配置文件到phoenix (hd100上执行)
[root@hd100 phoenix-5.0.0-HBase-2.0]# ls /home/hadoop/hbase/conf/hbase-site.xml /home/hadoop/hadoop/etc/hadoop/{core-site.xml,hdfs-site.xml}
/home/hadoop/hadoop/etc/hadoop/core-site.xml /home/hadoop/hadoop/etc/hadoop/hdfs-site.xml /home/hadoop/hbase/conf/hbase-site.xml
[root@hd100 phoenix-5.0.0-HBase-2.0]# cp /home/hadoop/hbase/conf/hbase-site.xml /home/hadoop/hadoop/etc/hadoop/{core-site.xml,hdfs-site.xml} /home/hadoop/phoenix-5.0.0-HBase-2.0/bin/
-
拷贝phoenix到其他节点 (hd100上执行)
[root@hd100 phoenix-5.0.0-HBase-2.0]# scp -r /home/hadoop/phoenix-5.0.0-HBase-2.0 hd110:/home/hadoop/
[root@hd100 phoenix-5.0.0-HBase-2.0]# scp -r /home/hadoop/phoenix-5.0.0-HBase-2.0 hd120:/home/hadoop/
-
拷贝phoenix的jar包到hbase中 (hd100上执行)(/home/hadoop/phoenix-5.0.0-HBase-2.0目录下)
[root@hd100 phoenix-5.0.0-HBase-2.0]# pwd
/home/hadoop/phoenix-5.0.0-HBase-2.0
[root@hd100 phoenix-5.0.0-HBase-2.0]# ls -l phoenix-5.0.0-HBase-2.0-server.jar phoenix-core-5.0.0-HBase-2.0.jar phoenix-5.0.0-HBase-2.0-client.jar
-rw-r--r-- 1 502 games 135109092 6月 27 2018 phoenix-5.0.0-HBase-2.0-client.jar
-rw-r--r-- 1 502 games 41800313 6月 27 2018 phoenix-5.0.0-HBase-2.0-server.jar
-rw-r--r-- 1 502 games 4317285 6月 27 2018 phoenix-core-5.0.0-HBase-2.0.jar
[root@hd100 phoenix-5.0.0-HBase-2.0]# scp phoenix-5.0.0-HBase-2.0-server.jar phoenix-core-5.0.0-HBase-2.0.jar phoenix-5.0.0-HBase-2.0-client.jar hd100:/home/hadoop/hbase/lib/
[root@hd100 phoenix-5.0.0-HBase-2.0]# scp phoenix-5.0.0-HBase-2.0-server.jar phoenix-core-5.0.0-HBase-2.0.jar phoenix-5.0.0-HBase-2.0-client.jar hd110:/home/hadoop/hbase/lib/
[root@hd100 phoenix-5.0.0-HBase-2.0]# scp phoenix-5.0.0-HBase-2.0-server.jar phoenix-core-5.0.0-HBase-2.0.jar phoenix-5.0.0-HBase-2.0-client.jar hd120:/home/hadoop/hbase/lib/
-
重启hbase
-
运行phoenix
/home/hadoop/phoenix-5.0.0-HBase-2.0目录下
[root@hd100 phoenix-5.0.0-HBase-2.0]# pwd
/home/hadoop/phoenix-5.0.0-HBase-2.0
首次启动会在hbase中自动生成5张表,在phoenix中也可以看到
[root@hd100 phoenix-5.0.0-HBase-2.0]# bin/sqlline.py
Setting property: [incremental, false]
Setting property: [isolation, TRANSACTION_READ_COMMITTED]
issuing: !connect jdbc:phoenix: none none org.apache.phoenix.jdbc.PhoenixDriver
Connecting to jdbc:phoenix:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/hadoop/phoenix-5.0.0-HBase-2.0/phoenix-5.0.0-HBase-2.0-client.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/hadoop/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
20/11/14 21:57:05 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Connected to: Phoenix (version 5.0)
Driver: PhoenixEmbeddedDriver (version 5.0)
Autocommit status: true
Transaction isolation: TRANSACTION_READ_COMMITTED
Building list of tables and columns for tab-completion (set fastconnect to true to skip)...
133/133 (100%) Done
Done
sqlline version 1.2.0
0: jdbc:phoenix:> !tables
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | TYPE_NAME | SELF_REFERENCING_COL_NAME | REF_GENERATION | INDEX_STATE | I |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
| | SYSTEM | CATALOG | SYSTEM TABLE | | | | | | f |
| | SYSTEM | FUNCTION | SYSTEM TABLE | | | | | | f |
| | SYSTEM | LOG | SYSTEM TABLE | | | | | | t |
| | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | | | f |
| | SYSTEM | STATS | SYSTEM TABLE | | | | | | f |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
0: jdbc:phoenix:>
3 SQL基本操作
-
说明
Phoenix 对表名和列名都是区分大小写的,但是,如果不加双引号,则默认为大写。
表名要和 HBase 中建立的表名一致。HBase 默认的主列名是 ROW,所以要将“ROW”设置为主键。列簇和列名也要用双引号括起来,要不然小写会自动变成大写。
删除映射表,会同时删除原有HBase表。 4.10之后的phoenix版本不能先创建表映射,再创建视图映射,否则会报错。
Phoenix 4.10 及以上的版本,可能会遇到查不出数据的情况。这是因为4.10 版本之后,Phoenix 对列的编码方式有所改变。那么如何解决这个问题呢?(官方文档地址:http://phoenix.apache.org/columnencoding.html)
在使用 Phoenix 创建表的时候,需要设置 COLUMN_ENCODED_BYTES 属性为 0,即不让 Phoenix 对 column family 进行编码。如:(只有在创建表的时候才能够设置属性。)
CREATE TABLE "test_table" ( "ROW" varchar primary key, "0"."name" varchar) column_encoded_bytes=0;
-
创建schema
create schema test;
-
创建表(建完表后hbase中也会自动创建对应的表)
create table test.t_test(
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR,
age INTEGER);
创建完的表名和字段名都会自动转成大写,如需小写,需在建表时给表名和字段名前后加双引号。
-
插入/更新数据
upsert into test.t_test (id,name,age) values(1,'zhangsan',23);
upsert into test.t_test (id,name,age) values(2,'lisi',35);
upsert into test.t_test (id,name,age) values(3,'测试',66);
-
查询插入的数据
0: jdbc:phoenix:> select * from test.t_test;
+-----+-----------+------+
| ID | NAME | AGE |
+-----+-----------+------+
| 1 | zhangsan | 23 |
| 2 | lisi | 35 |
| 3 | 测试 | 66 |
+-----+-----------+------+
3 rows selected (0.181 seconds)
-
添加索引字段
create index idx_name on test.t_test(name);
如果添加索引报错:
解决方法: 在hbase-site.xml 中配置中加入,重启服务
添加如下配置到Hbase的Hregionserver节点的hbase-site.xml
<property>
<!-- phoenix支持索引 -->
<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>
添加如下配置到Hbase中Hmaster节点的hbase-site.xml中
<!-- phoenix master 配置参数 -->
<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>
再次创建索引即可。
-
查看索引
!indexes test.t_test;
-
删除数据
delete from test.t_test where id =1;
-
删除表
drop table test.t_test;
-
删除schema
drop schema test;
以上在phoenix中的DDL和DML操作在hbase对应的表中也会同时触发,即操作通过phoenix来操作hbase。
-
退出
!quit
4 使用hbase shell创建表student
hbase(main):002:0> create 'student', 'info'
Created table student
Took 2.4457 seconds
=> Hbase::Table - student
hbase(main):003:0> lsit
NameError: undefined local variable or method `lsit' for main:Object
Did you mean? list
hbase(main):004:0> list
TABLE
student
1 row(s)
Took 0.0199 seconds
=> ["student"]
hbase(main):005:0> put 'student', '1001', 'info:name', '大刘'
Took 0.3448 seconds
hbase(main):006:0> put 'student', '1001', 'info:age', '100'
Took 0.0361 seconds
hbase(main):007:0> put 'student', '1002', 'info:name', '小星'
Took 0.0243 seconds
hbase(main):008:0> put 'student', '1002', 'info:age', '20'
Took 0.0247 seconds
hbase(main):009:0> scan "student"
ROW COLUMN+CELL
1001 column=info:age, timestamp=1605360191345, value=100
1001 column=info:name, timestamp=1605360191254, value=\xE5\xA4\xA7\xE5\x88\x98
1002 column=info:age, timestamp=1605360193826, value=20
1002 column=info:name, timestamp=1605360191399, value=\xE5\xB0\x8F\xE6\x98\x9F
2 row(s)
Took 0.1159 seconds
hbase(main):010:0>
5 表映射-映射已有的HBase表
表映射特点:在映射表中可以进行增删改查操作,如果在 phoenix中将映射表删除,hbase 中对应的表也会被删除。
-
在 phoenix 命令行中执行如下命令创建对应的映射表:
CREATE TABLE IF NOT EXISTS "student" (
"ROW" VARCHAR primary key,
"info"."name" VARCHAR,
"info"."age" VARCHAR
)column_encoded_bytes=0;
注意一:HBase 中的 RowKey 映射 Phoenix 的主键,HBase 中的 Column 映射 Phoenix 的列,且使用“列簇名.列名”进行映射。
注意二:末尾要加上 column_encoded_bytes=0,不加的话 select 时会出现查不出数据的情况。
-
查询一下可以看得到数据,说明映射成功:
0: jdbc:phoenix:> select * from "student";
+-------+-------+------+
| ROW | name | age |
+-------+-------+------+
| 1001 | 大刘 | 100 |
| 1002 | 小星 | 20 |
+-------+-------+------+
2 rows selected (0.113 seconds)
创建映射后 HBase 里表的数据可能会被清空,我们在 HBase 那边重新插入数据即可。
-
hbase 和 phoenix 无论哪一端插入/更新/删除数据,另一端对应的表都会同步插入/更新/删除。比如我们在 phoenix 这边插入一条数据:
0: jdbc:phoenix:> upsert into "student" values('1003','hangge','1');
1 row affected (0.111 seconds)
0: jdbc:phoenix:> select * from "student";
+-------+---------+------+
| ROW | name | age |
+-------+---------+------+
| 1001 | 大刘 | 100 |
| 1002 | 小星 | 20 |
| 1003 | hangge | 1 |
+-------+---------+------+
3 rows selected (0.044 seconds)
0: jdbc:phoenix:> upsert into "student" values('1004','swphonix','132');
1 row affected (0.018 seconds)
0: jdbc:phoenix:> select * from "student";
+-------+-----------+------+
| ROW | name | age |
+-------+-----------+------+
| 1001 | 大刘 | 100 |
| 1002 | 小星 | 20 |
| 1003 | hangge | 1 |
| 1004 | swphonix | 132 |
+-------+-----------+------+
4 rows selected (0.05 seconds)
0: jdbc:phoenix:>
-
hbase 这边也可以看到最新插入的数据:
hbase(main):001:0> scan "student"
ROW COLUMN+CELL
1001 column=info:age, timestamp=1605360191345, value=100
1001 column=info:name, timestamp=1605360191254, value=\xE5\xA4\xA7\xE5\x88\x98
1002 column=info:age, timestamp=1605360193826, value=20
1002 column=info:name, timestamp=1605360191399, value=\xE5\xB0\x8F\xE6\x98\x9F
1003 column=info:_0, timestamp=1605362895354, value=x
1003 column=info:age, timestamp=1605362895354, value=1
1003 column=info:name, timestamp=1605362895354, value=hangge
1004 column=info:_0, timestamp=1605362990307, value=x
1004 column=info:age, timestamp=1605362990307, value=132
1004 column=info:name, timestamp=1605362990307, value=swphonix
6 视图映射-映射已有的HBase表
视图映射特点:在映射表中只能进行查询操作,而不可以进行增删改操作。如果将 phoenix 中的映射表删除,hbase 中对应的表不会被删除。所以如果是“只读不写”最好使用视图映射,避免误删数据。
-
在 phoenix 命令行中执行如下命令创建对应的映射视图:
CREATE VIEW "student" (
"ROW" VARCHAR primary key,
"info"."name" VARCHAR,
"info"."age" VARCHAR
) as select * from "student";
需要注意的是 4.10之后的phoenix版本不能先创建表映射,再创建 视图映射。 否则会报错如下:
解决方法:新创建表格,把原来的数据导入新表中。
新建一个新的原生hbase表student_new
或在另一个schema下创建原生hbase表TEST:student
,在hbase的shell命令行中:
hbase(main):008:0> create 'student_new', 'info'
Created table student_new
...
hbase(main):009:0> create 'TEST:student', 'info'
Created table TEST:student
...
put 'TEST:student', '1001', 'info:name', '大刘'
put 'TEST:student', '1001', 'info:age', '100'
put 'TEST:student', '1002', 'info:name', '小星'
put 'TEST:student', '1002', 'info:age', '20'
put 'TEST:student', '1003', 'info:name', 'hangge'
put 'TEST:student', '1003', 'info:age', '1'
put 'TEST:student', '1004', 'info:name', 'swphonix'
put 'TEST:student', '1004', 'info:age', '132'
hbase(main):005:0> scan 'TEST:student'
ROW COLUMN+CELL
1001 column=info:age, timestamp=1605403412853, value=100
1001 column=info:name, timestamp=1605403388226, value=\xE5\xA4\xA7\xE5\x88\x98
1002 column=info:age, timestamp=1605403466025, value=20
1002 column=info:name, timestamp=1605403438041, value=\xE5\xB0\x8F\xE6\x98\x9F
1003 column=info:age, timestamp=1605405545685, value=1
1003 column=info:name, timestamp=1605405545616, value=hangge
1004 column=info:age, timestamp=1605405547490, value=132
1004 column=info:name, timestamp=1605405545787, value=swphonix
-
在 phoenix 命令行中执行如下命令创建对应的映射视图:
CREATE VIEW test."student" (
"ROW" VARCHAR primary key,
"info"."name" VARCHAR,
"info"."age" VARCHAR
) column_encoded_bytes=0;
0: jdbc:phoenix:> CREATE VIEW test."student" (
. . . . . . . . > "ROW" VARCHAR primary key,
. . . . . . . . > "info"."name" VARCHAR,
. . . . . . . . > "info"."age" VARCHAR
. . . . . . . . > ) column_encoded_bytes=0;
No rows affected (7.73 seconds)
0: jdbc:phoenix:> !table
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | TYPE_NAME | SELF_REFERENCING_COL_NAME | REF_GENERATION | INDEX_STATE | I |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
| | TEST | IDX_NAME | INDEX | | | | | ACTIVE | f |
| | SYSTEM | CATALOG | SYSTEM TABLE | | | | | | f |
| | SYSTEM | FUNCTION | SYSTEM TABLE | | | | | | f |
| | SYSTEM | LOG | SYSTEM TABLE | | | | | | t |
| | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | | | f |
| | SYSTEM | STATS | SYSTEM TABLE | | | | | | f |
| | | student | TABLE | | | | | | f |
| | TEST | T_TEST | TABLE | | | | | | f |
| | TEST | student | VIEW | | | | | | f |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+--------------+---+
0: jdbc:phoenix:> select * from test."student";
+-------+-----------+------+
| ROW | name | age |
+-------+-----------+------+
| 1001 | 大刘 | 100 |
| 1002 | 小星 | 20 |
| 1003 | hangge | 1 |
| 1004 | swphonix | 132 |
+-------+-----------+------+
4 rows selected (0.123 seconds)
-
关于映射的注意事项
1、需要将原有 HBase 中的表做映射才能后使用 Phoenix 操作。
2、Phoenix 区分大小写,切默认情况下会将小写转成大写,所以表名、列簇、列名需要用双引号。
3、Phoenix 4.10 版本之后,在创建表映射时需要将 COLUMN_ENCODED_BYTES 置为 0。
4、删除映射表,会同时删除原有 HBase 表。所以如果只做查询操作,建议做视图映射。
7 通过DBeaver连接Phoenix操作HBase
7.1 下载及安装
DBeaver官方:https://dbeaver.io/
下载社区版本进行安装即可:https://dbeaver.io/files/dbeaver-ce-latest-x86_64-setup.exe
7.2 启动及准备驱动包
启动DBeaver
-
准备好驱动包
到Phoenix安装路径下(/home/hadoop/phoenix-5.0.0-HBase-2.0),复制 phoenix-5.0.0-HBase-2.0-client.jar 到本机(不同版本的Phoenix的jar命名不同,但是都是client这个包)
[root@hd120 phoenix-5.0.0-HBase-2.0]# ls -l *client.jar
-rw-r--r-- 1 root root 135109092 11月 12 15:09 phoenix-5.0.0-HBase-2.0-client.jar
-rw-r--r-- 1 root root 34159398 11月 12 15:09 phoenix-5.0.0-HBase-2.0-thin-client.jar
到hbase配置目录下(/home/hadoop/hbase/conf),复制下载 hbase-site.xml到本机
把 hbase-site.xml直接拖放到phoenix-5.0.0-HBase-2.0-client.jar里面(相当于把hbase-site.xml压缩进phoenix-5.0.0-HBase-2.0-client.jar包里)(可以使用WinRAR进行操作)
7.3 创建数据库连接
-
数据库 > 新建连接
-
下一步:填写ip和端口 (zk集群的主机地址或主机名、端口2181)
-
编辑驱动设置
-
添加驱动:
点击“添加文件”,选择准备好的
phoenix-5.0.0-HBase-2.0-client.jar
如果此时驱动包有多个,请务必删除,只保留手动添加的
phoenix-5.0.0-HBase-2.0-client.jar
-
找到驱动类 点击“找到类”,选择
org.apache.phoenix.jdbc.PhoenixDriver
-
添加 Zookeeper Base Path 手动添加Zookeeper Base Path,这个路径可以在hbase的页面看到 (http://hd100:16010/master-status)
-
在
C:\Windows\System32\drivers\etc\hosts
添加主机列表
###hbase
192.168.26.100 hd100
192.168.26.110 hd110
192.168.26.120 hd120
-
测试连接
7.4 操作指引
-
成功连接Phoenix,导航面板及浏览表、视图
-
愉快的使用SQL查询
点击SQL编辑器,新建SQL编辑器
,输入SQL语句进行查询。 注意:SQL语句结尾不能带分号(;),执行的时候会自动加上;表名和字段名使用双引号,字符串值使用单引号
SELECT * FROM test."student" WHERE "name"='swphonix'
--OK--