一、 Phoenix简介
1、 Phoenix定义
Phoenix是HBase的开源SQL皮肤。可以使用标准JDBC API代替HBase客户端API来创建表,插入数据和查询HBase数据。
2、Phoenix特点支持标准化SQL,可以是hbase处理更加灵活复杂事务的能力。
完美支持Hbase二级索引创建。
容易集成:如Spark,Hive,Pig,Flume和Map Reduce。
3、Phoenix架构Phoenix架构
4、Phoenix的作用Phoenix的作用
二、Phoenix快速入门
1、Phoenix安装部署
phoenix压缩包,百度网盘:
(1)上转文件及解压文件
[root@hadoop1 module]# ll
total 338872
-rw-r--r--. 1 root root 346993138 May 12 09:35 apache-phoenix-4.14.1-HBase-1.3-bin.tar.gz
[root@hadoop1 module]# tar -zxvf apache-phoenix-4.14.1-HBase-1.3-bin.tar.gz
(2)拷贝phoenix-4.14.1-HBase-1.3-server.jar和phoenix-core-4.14.1-HBase-1.3.jar这俩个包拷贝到的hbase/lib文件下
//重命名[root@hadoop1 module]# mv apache-phoenix-4.14.1-HBase-1.3-bin phoenix-4.14
//server和client这俩个包拷贝到hbase/lib[root@hadoop1 phoenix-4.14]# cp phoenix-4.14.1-HBase-1.3-server.jar ../hbase-1.3.1/lib/
[root@hadoop1 phoenix-4.14]# cp phoenix-core-4.14.1-HBase-1.3.jar ../hbase-1.3.1/lib/
(3) 向每个节点分发
[root@hadoop1 module]# scp phoenix-4.14/ hadoop2.x:/usr/local/etc/hadoop/module/
[root@hadoop1 module]# scp phoenix-4.14/ hadoop3.x:/usr/local/etc/hadoop/module/
(4)配置Phoenix
//查看当前路径[root@hadoop1 conf]# pwd
/usr/local/etc/hadoop/module/hbase-1.3.1/conf
//将hbase的配置文件hbase-site.xml[root@hadoop1 conf]# cp hbase-site.xml ../../phoenix-4.14/bin/
//hadoop/etc/hadoop下的core-site.xml 、hdfs-site.xml放到phoenix/bin/下,替换phoenix原来的配置文件。[root@hadoop1 conf]# cp ../../hadoop-2.7.2/etc/hadoop/core-site.xml ../../phoenix-4.14/bin/
[root@hadoop1 conf]# cp ../../hadoop-2.7.2/etc/hadoop/hdfs-site.xml ../../phoenix-4.14/bin/
(5)在root权限下给/etc/profile 下添加如下内容
//phoenixexport PHOENIX_HOME=/usr/local/etc/hadoop/module/phoenix-4.14
export PHOENIX_CLASSPATH=$PHOENIX_HOME
export PATH=$PATH:$PHOENIX_HOME/bin
//环境变量生效[root@hadoop1 phoenix-4.14]# source /etc/profile
(6)启动Phoenix(启动Phoenix之前,需要先启动:Zookeeper,Hadoop,Hbase)
//启动的进程有:[root@hadoop1 conf]# jps -l
11009 org.apache.hadoop.yarn.server.nodemanager.NodeManager
10405 org.apache.hadoop.hdfs.server.namenode.NameNode
10885 org.apache.hadoop.yarn.server.resourcemanager.ResourceManager
11909 sqlline.SqlLine
11447 org.apache.hadoop.hbase.master.HMaster
12506 sun.tools.jps.Jps
10523 org.apache.hadoop.hdfs.server.datanode.DataNode
11595 org.apache.hadoop.hbase.regionserver.HRegionServer
10668 org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode
//在phoenix/bin下输入命令[root@hadoop1 bin]# ./sqlline.py hadoop1.x,hadoop2.x,hadoop3.x:2181
Setting property: [incremental, false]
Setting property: [isolation, TRANSACTION_READ_COMMITTED]
issuing: !connect jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x:2181 none none org.apache.phoenix.jdbc.PhoenixDriver
Connecting to jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x:2181
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/etc/hadoop/module/phoenix-4.14/phoenix-4.14.1-HBase-1.3-client.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/local/etc/hadoop/module/hadoop-2.7.2/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.20/05/23 08:19:33 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Connected to: Phoenix (version 4.14)
Driver: PhoenixEmbeddedDriver (version 4.14)
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:hadoop1.x,hadoop2.x,hadoop3.x>
2、phoenix表操作
(1)显示所有表
//!table 或 !tables:显示所有表0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> !table
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+---+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | TYPE_NAME | SELF_REFERENCING_COL_NAME | REF_GENERATION | I |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+---+
| | SYSTEM | CATALOG | SYSTEM TABLE | | | | | |
| | SYSTEM | FUNCTION | SYSTEM TABLE | | | | | |
| | SYSTEM | LOG | SYSTEM TABLE | | | | | |
| | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | | |
| | SYSTEM | STATS | SYSTEM TABLE | | | | | |
+------------+--------------+-------------+---------------+----------+------------+----------------------------+-----------------+---+
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x>
(2)创建表在phoenix中,默认情况下,表名等会自动转换为大写,若要小写,使用双引号,如"us_population"。
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> create table customer_0523(id varchar,name.first_name varchar,name.last_name varchar constraint my_pk primary key(id));
No rows affected (12.176 seconds)
//查询表
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> select * from customer_0523;
+-----+-------------+------------+
| ID | FIRST_NAME | LAST_NAME |
+-----+-------------+------------+
+-----+-------------+------------+
No rows selected (0.513 seconds)
//插入表
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> upsert into customer_0523 values(
. . . . . . . . . . . . . . . . . . . . . . .> '1','zhang','san');
1 row affected (0.143 seconds)
//查询表数据
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> select * from customer_0523;
+-----+-------------+------------+
| ID | FIRST_NAME | LAST_NAME |
+-----+-------------+------------+
| 1 | zhang | san |
+-----+-------------+------------+
1 row selected (0.37 seconds)
(3)常见sql操作
//插入记录select * from us_population ;
select * from us_population wherestate='NY';
//删除记录delete from us_population wherestate='NY';
//删除表drop table us_population;
//退出命令行!quit
3、phoenix表映射
(1)Phoenix和Hbase表的关系默认情况下,直接在hbase中创建的表,通过phoenix是查看不到的。如图1和图2,US_POPULATION是在phoenix中直接创建的,而kylin相关表是在hbase中直接创建的,在phoenix中是查看不到kylin等表的。图1 phoenix命令行中查看所有表:
图2 hbase命令行中查看所有表:如果要在phoenix中操作直接在hbase中创建的表,则需要在phoenix中进行表的映射。映射方式有两种:视图映射和表映射
(2)Hbase命令行中创建表test
Hbase 中test的表结构如下,两个列簇name、company.
[root@hadoop1 bin]# pwd
/usr/local/etc/hadoop/module/hbase-1.3.1/bin
启动Hbase shell[root@hadoop1 bin]# ./hbase shell
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/etc/hadoop/module/hbase-1.3.1/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/local/etc/hadoop/module/hadoop-2.7.2/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
HBase Shell; enter 'help' for list of supported commands.
Type "exit" to leave the HBase Shell
Version 1.3.1, r930b9a55528fe45d8edce7af42fef2d35e77677a, Thu Apr 6 19:36:54 PDT 2017
hbase(main):001:0>
//列出当前表hbase(main):001:0> list
TABLE
CUSTOMER_0523
SYSTEM.CATALOG
SYSTEM.FUNCTION
SYSTEM.LOG
SYSTEM.MUTEX
SYSTEM.SEQUENCE
SYSTEM.STATS
7 row(s) in 1.6650 seconds
=> ["CUSTOMER_0523", "SYSTEM.CATALOG", "SYSTEM.FUNCTION", "SYSTEM.LOG", "SYSTEM.MUTEX", "SYSTEM.SEQUENCE", "SYSTEM.STATS"]
hbase(main):002:0>
//以上发现,CUSTOMER_0523是刚才创建的,注意:在HBase中,创建的表会自动转成大写//我们先查询这张表hbase(main):002:0> scan 'CUSTOMER_0523'
ROW COLUMN+CELL
1 column=NAME:\x00\x00\x00\x00, timestamp=1590224130746, value=x
1 column=NAME:\x80\x0B, timestamp=1590224130746, value=zhang
1 column=NAME:\x80\x0C, timestamp=1590224130746, value=san
1 row(s) in 1.3720 seconds
若:我们在Hbase创建一张表,让phoenix查询出来
hbase(main):001:0> create 'test','name','company'
创建表,如下图:
(3)视图映射Phoenix创建的视图是只读的,所以只能用来做查询,无法通过视图对源数据进行修改等操作。在phoenix中创建视图test表
0: jdbc:phoenix:hadoop101,hadoop102,hadoop103> create view "test"(empid varchar primary key,"name"."firstname" varchar,"name"."lastname" varchar,"company"."name" varchar,"company"."address" varchar);删除视图
0: jdbc:phoenix:hadoop101,hadoop102,hadoop103> drop view "test";
(4)表映射
使用Apache Phoenix创建对HBase的表映射,有两种方法:当HBase中已经存在表时,可以以类似创建视图的方式创建关联表,只需要将create view改为create table即可。
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> create table "test"(empid varchar primary key,"name"."firstname" varchar,"name"."lastname" varchar,"company"."name" varchar,"company"."address" varchar);当HBase中不存在表时,可以直接使用create table指令创建需要的表,系统将会自动在Phoenix和HBase中创建person_infomation的表,并会根据指令内的参数对表结构进行初始化。
0: jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x> create table "test"(empid varchar primary key,"name"."firstname" varchar,"name"."lastname" varchar,"company"."name" varchar,"company"."address" varchar) column_encoded_bytes=0;
三、Squirrel可视化连接Phoenix
1、下载Squirrel的jar包官方网址Squirrel的jar包官方
百度网盘提供资料
提取码:pfve
接下来,工具安装,一直点击next即可
2、配置Squirrel连接到Phoenix
(1) 复制Phoenix的client.jar包到E:\Linux\phoenix\squirrel-sql-3.9.1\lib下
3、在Windows环境下安装Squirrel程序
(1)启动Squirrel
(2)添加Driver具体配置信息添加Driver具体配置信息
配置信息:Name=Phoenix Example URL = jdbc:phoenix:hadoop1.x,hadoop2.x,hadoop3.x:2181
Java Class Path 选择E:\Linux\phoenix\pathclass\lib\phoenix-4.14.2-HBase-1.3-client.jar
Class Name= org.apache.phoenix.jdbc.PhoenixDriver
(3)配置Aliases
连接上,如图所示:
(4)使用Squirrel查询数据Squirrel查询数据
4、HBase操作
//创建数据表,名叫“customer0523_2”hbase(main):001:0> create 'customer0523_2','info'
0 row(s) in 2.6110 seconds
=> Hbase::Table - customer0523_2
//在customer0523_2表插入数hbase(main):001:0> put 'customer0523_2','1011','info:name','zhangsan'
0 row(s) in 0.5940 seconds
put 'customer0523_2','1011','info:age','33'
0 row(s) in 0.0200 seconds
//查询customer0523_2表的数据hbase(main):003:0> get 'customer0523_2','1011'
COLUMN CELL
info:age timestamp=1590316173222, value=33
info:name timestamp=1590316158203, value=zhangsan
1 row(s) in 0.1720 seconds
//另一种方式查询表,采用“scan”hbase(main):004:0> scan 'customer0523_2'
ROW COLUMN+CELL
1011 column=info:age, timestamp=1590316173222, value=33
1011 column=info:name, timestamp=1590316158203, value=zhangsan
1 row(s) in 0.0490 seconds
注意:若在hbase中创建的表,在phoenix是没有(没有映射),我们可以在SQuirreL SQL Client工具编写作映射当HBase中不存在表时,可以直接使用create table指令创建需要的表,系统将会自动在Phoenix和HBase中创建person_infomation的表,并会根据指令内的参数对表结构进行初始化。
create table "customer0523_2" ("id" varchar primary key ,"info"."name" varchar ,"info"."age" varchar)column_encoded_bytes=0;
如图所示:
当可以执行出来,我们就可以对这表进行查询,执行sql语句:
select * from "customer0523_2"
如图所示:
HBase将衍生一条数据:
hbase(main):001:0> scan 'customer0523_2'
ROW COLUMN+CELL
1011 column=info:_0, timestamp=1590316173222, value=
1011 column=info:age, timestamp=1590316173222, value=33
1011 column=info:name, timestamp=1590316158203, value=zhangsan
1 row(s) in 0.5730 seconds
5、视图映射和表映射的对比与总结相比于直接创建映射表,视图的查询效率会低,原因是:创建映射表的时候,Phoenix会在表中创建一些空的键值对,这些空键值对的存在可以用来提高查询效率。
使用create table创建的关联表,如果对表进行了修改,源数据也会改变,同时如果关联表被删除,源表也会被删除。但是视图就不会,如果删除视图,源数据不会发生改变。
四、 Phoenix创建Hbase二级索引
1、 配置Hbase支持Phoenix创建二级索引
(1)添加如下配置到Hbase的Hregionserver节点的hbase-site.xml
hbase.regionserver.wal.codec
org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec
hbase.region.server.rpc.scheduler.factory.class
org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory
Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates
hbase.rpc.controllerfactory.class
org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory
Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates
(2)添加如下配置到Hbase中Hmaster节点的hbase-site.xml中
hbase.master.loadbalancer.class
org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer
hbase.coprocessor.master.classes
org.apache.phoenix.hbase.index.master.IndexMasterObserver
全局索引(多读少写)
create index idx_c0523_name_2 on "customer0523_2"("info"."name")
create index idx_c0523_name_3 on "customer0523_2"("info"."name")include ("info"."age")
explain select "age" from "customer0523_2" where "name"="zhangsan"
本地索引(多写少读)推荐:在原有的rowkey基础上,在加索引列与主键对应关系
create local index idx_c0523_name_lcl on "customer0523_2" ("info"."age")
explain select * from "customer0523_2" where "age" ="33"
2、 phoenix的索引分类global index是默认的索引格式。适用于多读少写的业务场景。写数据的时候会消耗大量开销,因为索引表也要更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。
CREATE INDEX my_index ON my_table (my_col)Local index适用于写操作频繁的场景。索引数据和数据表的数据是存放在相同的服务器中的,避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升。
CREATE LOCAL INDEX my_index ON my_table (my_index)
建立local index可能出现的问题:
hbase-site.xml的zookeeeper的配置信息不能加2181,否则在创建local index的时候会报以下异常:
正常配置:
hbase.zookeeper.quorum
hadoop1.x,hadoop2.x,hadoop3.x
Local index 和 Global index区别:Local index 由于是数据与索引在同一服务器上,所以要查询的数据在哪台服务器的哪个region是无法定位的,只能先找到region然后在利用索引。
Global index 是一种分布式索引,可以直接利用索引定位服务器和region,速度更快,但是由于分布式的原因,数据一旦出现新增变化,分布式的索引要进行跨服务的同步操作,带来大量的通信消耗。所以在写操作频繁的字段上不适合建立Global index。
3、三种提升效率查询方式
1) CREATE INDEX my_index ON my_table (v1) INCLUDE (v2)
2) SELECT /*+ INDEX(my_table my_index) */ v2 FROM my_table WHERE v1 = 'foo'
3) CREATE LOCAL INDEX my_index ON my_table (v1)
4、如何删除索引
DROP INDEX my_index ON my_table
五、加盐表
1、phoenix怎么解决热点问题、数据分散?
可以在j建表时,加一个盐值(SALT_BUCKETS = 3)
如:
create table "user333" ( "user_id" varchar primary key , "info"."name" varchar , "info"."age" varchar)column_encoded_bytes=0,SALT_BUCKETS = 3
2、什么是加盐?
在密码学中,加盐是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同。
3、为什么加盐
如果主键的是顺序的序列,在频繁插入phoenix 到表中,最终会数据不停的落在一个regionServer中,容易造成热点问题。所以尽量将id打散。
利用表中定义盐值,数据会均匀的分布在各个region中。
4、盐值如何设?hbase节点数的倍数,最少是1倍
数据量大时可增加盐数,比如对于8个region server集群的大表,可以考虑设计64~128个slat buckets。