《Phoenix使用总结》 一、使用背景

使用背景

项目中有一个 HBase 表需要根据特定的条件进行查询,并且无法通过一次 rowkey 的设计达到很好的效果。第一版,在 MongoDB 中对 HBase 表的数据建立一张映射表,通过查询条件在 MongoDB 中查询出 RowKey,再到 HBase 中通过 RowKey 进行查询。
到后期由于数据量的增大(20亿),MongoDB所在的机器负载太高。后面通过讨论,使用 Phoenix 做二级索引进行查询。

Phoenix 简介

Phoenix 是开源的构建于 HBase 之上的 SQL 层,使我们能够使用标准的 JDBC API 代替 HBase Client API 操作 Hbase 进行创建表、插入数据和查询数据。

Apache Phoenix 结合以下两点实现在 Hadoop 中低延迟的 OLTP 和 operational analytics:

  • 强大的标准SQL和完整 ACID 事务的 JDBC APIs
  • 通过利用 HBase 作为后台存储,提供了NoSQL的late-bound, schema-on-read灵活的功能。

官网:http://phoenix.apache.org/

Quick Start

连接

Maven依赖

1
2
3
4
5
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>4.14.0-cdh5.13.2</version>
</dependency>

JDBC 连接

1
2
Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
Connection connection = DriverManager.getConnection("jdbc:phoenix:dmp-test01,dmp-test02,dmp-test03:2181");

DBCP 连接

1
2
3
4
BasicDataSource xdataSource = new BasicDataSource();
dataSource.setDriverClassName("org.apache.phoenix.jdbc.PhoenixDriver");
dataSource.setUrl("jdbc:phoenix:datanode03,datanode04,datanode05:2181");
Connection connection = dataSource.getConnection();

可以参考我写的工具类:PhoenixDbcpUtils.java

语法

Phoenix 的语法:http://phoenix.apache.org/language/index.html

示例

建表

1
2
3
4
5
6
7
8
9
10
CREATE TABLE IF NOT EXISTS PUBG.MATCH_INDEX (
lowerNickName VARCHAR NOT NULL,
startedAt DATE NOT NULL,
matchId VARCHAR,
mode VARCHAR,
queueSize INTEGER,
totalRank INTEGER,
type VARCHAR,
CONSTRAINT match_index_pk PRIMARY KEY (lowerNickName, startedAt))
SALT_BUCKETS = 100;

HBase 中有一个预分区的概念,防止热数据。Phoenix 建表时预分区的方案有两种,一种是使用 SPLIT ON 语句(与 HBase 的 SPLITS 概念一样),另一种是 Salted Tables ,建表时指定 SALT_BUCKETS 数量,具体可参考:http://phoenix.apache.org/salted.html

建立本地索引

1
CREATE LOCAL INDEX match_index_qm ON PUBG.MATCH_INDEX(lowerNickName, type, mode, queueSize, startedAt DESC) INCLUDE (matchId, totalRank) 

插入数据

1
UPSERT INTO PUBG.MATCH_INDEX(LOWERNICKNAME, STARTEDAT, MATCHID, MODE, QUEUESIZE, TOTALRANK, TYPE) VALUES (?, ?, ?, ?, ? ,?, ?)