Phoenix

Hbase适合存储大量的对关系运算要求低的NOSQL数据,受Hbase 设计上的限制不能直接使用原生的API执行在关系数据库中普遍使用的条件判断和聚合等操作。Hbase很优秀,一些团队寻求在Hbase之上提供一种更面向普通开发人员的操作方式,Apache Phoenix即是。

Phoenix 基于Hbase给面向业务的开发人员提供了以标准SQL的方式对Hbase进行查询操作,并支持标准SQL中大部分特性:条件运算,分组,分页,等高级查询语法。

1、Phoenix搭建

Phoenix 4.15 HBase 1.4.6 hadoop 2.7.6

1、关闭hbase集群,在master中执行

stop-hbase.sh

2、上传解压配置环境变量

解压

tar -xvf apache-phoenix-4.15.0-HBase-1.4-bin.tar.gz -C /usr/local/soft/

改名

mv apache-phoenix-4.15.0-HBase-1.4-bin phoenix-4.15.0

3、将phoenix-4.15.0-HBase-1.4-server.jar复制到所有节点的hbase lib目录下

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar master:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node1:/usr/local/soft/hbase-1.4.6/lib/

scp /usr/local/soft/phoenix-4.15.0/phoenix-4.15.0-HBase-1.4-server.jar node2:/usr/local/soft/hbase-1.4.6/lib/

4、启动hbase , 在master中执行

start-hbase.sh

5、配置环境变量

vim /etc/profile

2、Phoenix使用

1、连接sqlline

sqlline.py master,node1,node2

# 出现
163/163 (100%) Done
Done
sqlline version 1.5.0
0: jdbc:phoenix:master,node1,node2>

2、常用命令

# 1、创建表

CREATE TABLE IF NOT EXISTS STUDENT (
id VARCHAR NOT NULL PRIMARY KEY,
name VARCHAR,
age BIGINT,
gender VARCHAR ,
clazz VARCHAR
); # 2、显示所有表
!table # 3、插入数据
upsert into STUDENT values('1500100004','葛德曜',24,'男','理科三班');
upsert into STUDENT values('1500100005','宣谷芹',24,'男','理科六班');
upsert into STUDENT values('1500100006','羿彦昌',24,'女','理科三班'); # 4、查询数据,支持大部分sql语法,
select * from STUDENT ;
select * from STUDENT where age=24;
select gender ,count(*) from STUDENT group by gender;
select * from student order by gender; # 5、删除数据
delete from STUDENT where id='1500100004'; # 6、删除表
drop table STUDENT; # 7、退出命令行
!quit 更多语法参照官网
https://phoenix.apache.org/language/index.html#upsert_select

3、phoenix表映射

默认情况下,直接在hbase中创建的表,通过phoenix是查看不到的

如果需要在phoenix中操作直接在hbase中创建的表,则需要在phoenix中进行表的映射。映射方式有两种:视图映射和表映射

3.1、视图映射

Phoenix创建的视图是只读的,所以只能用来做查询,无法通过视图对源数据进行修改等操作

# hbase shell 进入hbase命令行
hbase shell # 创建hbase表
create 'test','name','company' # 插入数据
put 'test','001','name:firstname','zhangsan1'
put 'test','001','name:lastname','zhangsan2'
put 'test','001','company:name','数加'
put 'test','001','company:address','合肥' # 在phoenix创建视图, primary key 对应到hbase中的rowkey create view "test"(
empid varchar primary key,
"name"."firstname" varchar,
"name"."lastname" varchar,
"company"."name" varchar,
"company"."address" varchar
); CREATE view "student" (
id VARCHAR NOT NULL PRIMARY KEY,
"info"."name" VARCHAR,
"info"."age" VARCHAR,
"info"."gender" VARCHAR ,
"info"."clazz" VARCHAR
) column_encoded_bytes=0; # 在phoenix查询数据,表名通过双引号引起来
select * from "test"; # 删除视图
drop view "test";

3.2、表映射

使用Apache Phoenix创建对HBase的表映射,有两类:

1) 当HBase中已经存在表时,可以以类似创建视图的方式创建关联表,只需要将create view改为create table即可。

2)当HBase中不存在表时,可以直接使用create table指令创建需要的表,并且在创建指令中可以根据需要对HBase表结构进行显示的说明。

第1)种情况下,如在之前的基础上已经存在了test表,则表映射的语句如下:

create table "test" (
empid varchar primary key,
"name"."firstname" varchar,
"name"."lastname"varchar,
"company"."name" varchar,
"company"."address" varchar
)column_encoded_bytes=0; upsert into "test" values('1','2','3','4','5'); CREATE table "student" (
id VARCHAR NOT NULL PRIMARY KEY,
"info"."name" VARCHAR,
"info"."age" VARCHAR,
"info"."gender" VARCHAR ,
"info"."clazz" VARCHAR
) column_encoded_bytes=0; upsert into "student" values('1500110004','葛德曜','24','n ü','理科三班');

使用create table创建的关联表,如果对表进行了修改,源数据也会改变,同时如果关联表被删除,源表也会被删除。但是视图就不会,如果删除视图,源数据不会发生改变。

3、Phoenix二级索引

二级索引:建立行键与列值的映射关系

对于Hbase,如果想精确定位到某行记录,唯一的办法就是通过rowkey查询。如果不通过rowkey查找数据,就必须逐行比较每一行的值,对于较大的表,全表扫描的代价是不可接受的。

1、开启索引支持

# 关闭hbase集群
stop-hbase.sh # 在/usr/local/soft/hbase-1.4.6/conf/hbase-site.xml中增加如下配置 <property>
<name>hbase.regionserver.wal.codec</name>
<value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
<property>
<name>hbase.rpc.timeout</name>
<value>60000000</value>
</property>
<property>
<name>hbase.client.scanner.timeout.period</name>
<value>60000000</value>
</property>
<property>
<name>phoenix.query.timeoutMs</name>
<value>60000000</value>
</property> # 同步到所有节点
scp hbase-site.xml node1:`pwd`
scp hbase-site.xml node2:`pwd` # 修改phoenix目录下的bin目录中的hbase-site.xml
<property>
<name>hbase.rpc.timeout</name>
<value>60000000</value>
</property>
<property>
<name>hbase.client.scanner.timeout.period</name>
<value>60000000</value>
</property>
<property>
<name>phoenix.query.timeoutMs</name>
<value>60000000</value>
</property> # 启动hbase
start-hbase.sh
# 重新进入phoenix客户端
sqlline.sql master,node1,node2

2、创建索引

2.1、全局索引

全局索引适合读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)

注意: 对于全局索引在默认情况下,在查询语句中检索的列如果不在索引表中,Phoenix不会使用索引表将,除非使用hint。

# 创建DIANXIN.sql
CREATE TABLE IF NOT EXISTS DIANXIN (
mdn VARCHAR ,
start_date VARCHAR ,
end_date VARCHAR ,
county VARCHAR,
x DOUBLE ,
y DOUBLE,
bsid VARCHAR,
grid_id VARCHAR,
biz_type VARCHAR,
event_type VARCHAR ,
data_source VARCHAR ,
CONSTRAINT PK PRIMARY KEY (mdn,start_date)
) column_encoded_bytes=0; # 上传数据DIANXIN.csv # 导入数据
psql.py master,node1,node2 DIANXIN.sql DIANXIN.csv # 创建全局索引
CREATE INDEX DIANXIN_INDEX ON DIANXIN ( end_date );
索引名 哪张表 # 查询数据 ( 索引未生效)
select * from DIANXIN where end_date = '20180503154014';
# 索引未生效就还是去原始表查,不是去索引表查
# 运行超过1秒,不算是实时的 # 强制使用索引 (索引生效) hint
# /*+ INDEX(DIANXIN DIANXIN_INDEX) */ 算是提示
select /*+ INDEX(DIANXIN DIANXIN_INDEX) */ * from DIANXIN where end_date = '20180503154014'; select /*+ INDEX(DIANXIN DIANXIN_INDEX) */ * from DIANXIN where end_date = '20180503154014' and start_date = '20180503154614'; # 取索引列,(索引生效)
select end_date from DIANXIN where end_date = '20180503154014'; # 创建多列索引
CREATE INDEX DIANXIN_INDEX1 ON DIANXIN ( end_date,COUNTY ); # 多条件查询 (索引生效)
select end_date,MDN,COUNTY from DIANXIN where end_date = '20180503154014' and COUNTY = '8340104'; # 查询所有列 (索引未生效)
select * from DIANXIN where end_date = '20180503154014' and COUNTY = '8340104'; # 查询所有列 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX1) */ * from DIANXIN where end_date = '20180503154014' and COUNTY = '8340104'; # 单条件 (索引未生效) 返回慢
select end_date from DIANXIN where COUNTY = '8340103'; #CREATE INDEX DIANXIN_INDEX1 ON DIANXIN ( end_date,COUNTY );
#end_date 在前,row前缀过滤器,效率快 # 单条件 (索引生效) end_date 在前 返回快
select COUNTY from DIANXIN where end_date = '20180503154014'; # 删除索引
drop index DIANXIN_INDEX on DIANXIN; #单独启动regionServer
./hbase-daemon.sh start regionserver

2.2、本地索引

本地索引适合写多读少的场景,或者存储空间有限的场景。和全局索引一样,Phoenix也会在查询的时候自动选择是否使用本地索引。本地索引因为索引数据和原数据存储在同一台机器上,避免网络数据传输的开销,所以更适合写多的场景。由于无法提前确定数据在哪个Region上,所以在读数据的时候,需要检查每个Region上的数据从而带来一些性能损耗。

注意:对于本地索引,查询中无论是否指定hint或者是查询的列是否都在索引表中,都会使用索引表。

# 创建本地索引
CREATE LOCAL INDEX DIANXIN_LOCAL_IDEX ON DIANXIN(grid_id); # 索引生效
select grid_id from dianxin where grid_id='117285031820040'; # 索引生效
select * from dianxin where grid_id='117285031820040';
# 因为DIANXIN表数据大,所以速度比较慢

2.3、覆盖索引

覆盖索引是把原数据存储在索引数据表中,这样在查询时不需要再去HBase的原表获取数据就,直接返回查询结果。

相当于全局索引+数据

注意:查询是 select 的列和 where 的列都需要在索引中出现。

# 创建覆盖索引
CREATE INDEX DIANXIN_INDEX_COVER ON DIANXIN ( x,y ) INCLUDE ( county ); # 查询所有列 (索引未生效)
select * from DIANXIN where x=117.288 and y =31.822; # 强制使用索引 (索引生效)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ * from DIANXIN where x=117.288 and y =31.822; # 查询索引中的列 (索引生效) mdn是DIANXIN表的RowKey中的一部分
select x,y,county from DIANXIN where x=117.288 and y =31.822;
select mdn,x,y,county from DIANXIN where x=117.288 and y =31.822; # 查询条件必须放在索引中 select 中的列可以放在INCLUDE (将数据保存在索引中)
select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ x,y,count(*) from DIANXIN group by x,y;

4、Phoenix JDBC

# 导入依赖

<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>4.15.0-HBase-1.4</version>
</dependency>
package com.gym.HBase;

import java.sql.*;

/**
* @
* @create 2021-12-04-21:11
* @create 明天吃烤肉
*/
public class Demo7PhoenixJDBC {
public static void main(String[] args) throws SQLException { //1.创建连接
Connection conn = DriverManager.getConnection("jdbc:phoenix:master,node1,node2:2181"); //
PreparedStatement ps = conn.prepareStatement("select /*+ INDEX(DIANXIN DIANXIN_INDEX_COVER) */ * from DIANXIN where x=? and y =?"); //
ps.setDouble(1, 117.233);
ps.setDouble(2, 31.833); ResultSet rs = ps.executeQuery();
while (rs.next()) {
String mdn = rs.getString("mdn");
String start_date = rs.getString("start_date");
String end_date = rs.getString("end_date");
String county = rs.getString("county"); System.out.println(mdn + "," + start_date + "," + end_date + "," + county); }
ps.close();
conn.close();
}
}

Phoenix二级索引的更多相关文章

  1. Phoenix二级索引(Secondary Indexing)的使用

    摘要 HBase只提供了一个基于字典排序的主键索引,在查询中你只能通过行键查询或扫描全表来获取数据,使用Phoenix提供的二级索引,可以避免在查询数据时全表扫描,提高查过性能,提升查询效率   测试 ...

  2. [Phoenix] 五、二级索引

    摘要: 目前HBASE只有基于字典序的主键索引,对于非主键过滤条件的查询都会变成扫全表操作,为了解决这个问题Phoenix引入了二级索引功能.然而此二级索引又有别于传统关系型数据库的二级索引,本文将详 ...

  3. HBase二级索引、读写流程

    HBase二级索引.读写流程 一.HBse二级索引方案 1.1 基于Coprocessor方案 1.2 Phoenix二级索引特点 1.3 Phoenix 二级索引方案 二.HBase读写流程 2.1 ...

  4. HBase学习(四) 二级索引 rowkey设计

    HBase学习(四) 一.HBase的读写流程 画出架构 1.1 HBase读流程 Hbase读取数据的流程:1)是由客户端发起读取数据的请求,首先会与zookeeper建立连接2)从zookeepe ...

  5. HBase的二级索引,以及phoenix的安装(需再做一次)

    一:HBase的二级索引 1.讲解 uid+ts 11111_20161126111111:查询某一uid的某一个时间段内的数据 查询某一时间段内所有用户的数据:按照时间 索引表 rowkey:ts+ ...

  6. 085 HBase的二级索引,以及phoenix的安装(需再做一次)

    一:问题由来 1.举例 有A列与B列,分别是年龄与姓名. 如果想通过年龄查询姓名. 正常的检索是通过rowkey进行检索. 根据年龄查询rowkey,然后根据rowkey进行查找姓名. 这样的效率不高 ...

  7. Phoenix系列:二级索引(2)

    上一篇介绍了Phoenix基于HBase的二级索引的基本知识,这一篇介绍一下和索引相关的一致性和优化相关内容. 一致性的保证 Phoenix客户端在成功提交一个操作并且得到成功响应后,就代表你所做的操 ...

  8. Phoenix系列:二级索引(1)

    Phoenix使用HBase作为后端存储,对于HBase来说,我们通常使用字典序的RowKey来快速访问数据,除此之外,也可以使用自定义的Filter来搜索数据,但是它是基于全表扫描的.而Phoeni ...

  9. 通过phoenix在hbase上创建二级索引,Secondary Indexing

    环境描述: 操作系统版本:CentOS release 6.5 (Final) 内核版本:2.6.32-431.el6.x86_64 phoenix版本:phoenix-4.10.0 hbase版本: ...

随机推荐

  1. 奇偶位交换 牛客网 程序员面试金典 C++ Python

    奇偶位交换 牛客网 程序员面试金典 C++ Python 题目描述 请编写程序交换一个数的二进制的奇数位和偶数位.(使用越少的指令越好) 给定一个int x,请返回交换后的数int. 测试样例: 10 ...

  2. reorder-list leetcode C++

    Given a singly linked list L: L 0→L 1→-→L n-1→L n, reorder it to: L 0→L n →L 1→L n-1→L 2→L n-2→- You ...

  3. NOIP模拟88(多校21)

    前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...

  4. JVM-内存区域与OOM

    本篇博客内容主要参考<深入理解Java虚拟机> 内存区域与内存溢出异常 运行时数据区 Java虚拟机运行时数据区: 程序计数器(Program Counter Register)是一块较小 ...

  5. 在线编辑Word——插入图表

    在Word中可插入图表,配合使用表格能够更加全方位的展示数据的可信度并增加数据的可读性.本文将通过使用在线编辑器 Spire.Cloud Word 演示如何来插入图表,并设置相关格式化操作.具体步骤如 ...

  6. Java基础复习之数组

    Java基础复习之:数组 简介 数组(Array):多个相同数据类型按照一定顺序排列的集合,并使用一个名字命名,通过编号的方式对这些数据进行统一管理 一维数组 一维数组的声明与初始化 int[] id ...

  7. Javafx-【直方图】文本频次统计工具 中文/英文单词统计

    上周倒腾了下 javafx,本来是做平时成绩系统.跟老师提了一下 javafx,他突然兴起,发了个统计中文和英文单词并以直方图显示的实验......只给两三天的期限,笑着说考验我们的潜力SOS,于是带 ...

  8. js 事件流和事件冒泡阻止

    js 事件流和事件冒泡阻止 事件流 当浏览器发展到第四代的时候(IE4与Netscape4)浏览器开发团队遇到一个有意思的的问题: 页面的哪一部分会拥有某个特定的事件? 比如在纸上画上一组同心圆,如果 ...

  9. 环境(6)Linux文件系统二

    一:计算机间的数据传输 windows---linux : lrzsz  :需要手动安装 yum  install  lrzsz  -y   ;   rz  将文件从window上传到linux  : ...

  10. Sqlserver中判断表是否存在

    在sqlserver(应该说在目前所有数据库产品)中创建一个资源如表,视图,存储过程中都要判断与创建的资源是否已经存在  在sqlserver中一般可通过查询sys.objects系统表来得知结果,不 ...