Apache Phoenix的安装以及结合HBase的Java API使用

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Apache Phoenix的安装以及结合HBase的Java API使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Phoenix概述

Phoenix是一个基于HBase的开源SQL引擎,可以使用标准的JDBC API代替HBase客户端API来创建表,插入数据,查询你的HBase数据,它是完全使用Java编写,作为HBase内嵌的JDBC驱动使用。

Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫描,并编排执行以生成标准的JDBC结果集。

直接使用HBase API、协同处理器与自定义过滤器,对于简单查询来说,其性能量级是毫秒,对于百万级别的行数来说,其性能量级是秒。

官网:https://phoenix.apache.org/index.html

官网下载:https://phoenix.apache.org/download.html

开源软件镜像站下载:https://mirrors.bfsu.edu.cn/apache//phoenix

Phoenix下载与安装

下载

wget https://mirrors.bfsu.edu.cn/apache/phoenix/phoenix-5.1.2/phoenix-hbase-2.2-5.1.2-bin.tar.gz

解压与重命名

tar -zxvf phoenix-hbase-2.2-5.1.2-bin.tar.gz 

mv phoenix-hbase-2.2-5.1.2-bin phoenix-hbase

修改环境变量

vim /etc/profile

export PHOENIX_HOME=/usr/local/program/phoenix-hbase
export PATH=$PHOENIX_HOME/bin:$PATH

使生效 source /etc/profile

修改配置文件

修改phoenix-hbase/bin/hbase-site.xml

<configuration>
  <!-- 开启二级索引,默认 -->
  <property>
    <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
  </property>
  <!-- 开启schema与namespace的映射 -->
  <property>
      <name>phoenix.schema.isNamespaceMappingEnabled</name>
      <value>true</value>
  </property>
  <!-- SystemTables映射到namespace -->
  <property>
    <name>phoenix.schema.mapSystemTablesToNamespace</name>
    <value>true</value>
  </property>
</configuration>

修改HBase/conf/hbase-site.xml,添加如下配置

   <!-- 开启二级索引,默认 -->
  <property>
    <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
  </property>
  <!-- 开启schema与namespace的映射 -->
  <property>
      <name>phoenix.schema.isNamespaceMappingEnabled</name>
      <value>true</value>
  </property>
  <!-- SystemTables映射到namespace -->
  <property>
    <name>phoenix.schema.mapSystemTablesToNamespace</name>
    <value>true</value>
  </property>

拷贝jar包

Phoenix是以JDBC驱动方式嵌入到HBase中的,在部署时只有一个包,直接放HBase的lib目录

phoenix-hbase/phoenix-server-hbase-2.2-5.1.2.jar复制一份到HBase/lib/目录

启动Zookeeper、Hadoop、HBase、

zkServer.sh start

start-all.sh

start-hbase.sh

启动Phoenix

phoenix-hbase\bin>sqlline.py node001:2181

Connecting to jdbc:phoenix:node001:2181
Connected to: Phoenix (version 5.1)
Driver: PhoenixEmbeddedDriver (version 5.1)
Autocommit status: true
Transaction isolation: TRANSACTION_READ_COMMITTED
sqlline version 1.9.0
0: jdbc:phoenix:node001:2181>

退出

!quit

基本操作

详细用法参考:https://phoenix.apache.org/language/index.html
在这里插入图片描述

查看所有表

首次启动会在hbase中自动生成8张表

0: jdbc:phoenix:node001:2181> !table
+-----------+-------------+------------+--------------+---------+-----------+---------------------------+----------------+-------------+----------------+--------------+--------------+----------------+-----+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME |  TABLE_TYPE  | REMARKS | TYPE_NAME | SELF_REFERENCING_COL_NAME | REF_GENERATION | INDEX_STATE | IMMUTABLE_ROWS | SALT_BUCKETS | MULTI_TENANT | VIEW_STATEMENT | VIE |
+-----------+-------------+------------+--------------+---------+-----------+---------------------------+----------------+-------------+----------------+--------------+--------------+----------------+-----+
|           | SYSTEM      | CATALOG    | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
|           | SYSTEM      | CHILD_LINK | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
|           | SYSTEM      | FUNCTION   | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
|           | SYSTEM      | LOG        | SYSTEM TABLE |         |           |                           |                |             | true           | 32           | false        |                |     |
|           | SYSTEM      | MUTEX      | SYSTEM TABLE |         |           |                           |                |             | true           | null         | false        |                |     |
|           | SYSTEM      | SEQUENCE   | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
|           | SYSTEM      | STATS      | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
|           | SYSTEM      | TASK       | SYSTEM TABLE |         |           |                           |                |             | false          | null         | false        |                |     |
+-----------+-------------+------------+--------------+---------+-----------+---------------------------+----------------+-------------+----------------+--------------+--------------+----------------+-----+

在这里插入图片描述

创建schema

 create schema test;

创建表

1.建表后hbase中也会自动创建对应的表

2.建表后,表名和字段名都会自动转成大写,如需小写,需在建表时给表名和字段名前后加双引号

create table test.user(
	id INTEGER NOT NULL PRIMARY KEY,
	name VARCHAR,
	age INTEGER
);

在这里插入图片描述

插入与更新数据

upsert into test.user(id,name,age) values(1,'hbase1',20);
upsert into test.user(id,name,age) values(2,'hbase2',22);

查询数据

select * from test.user;

删除数据

delete from test.user where id =1;

删除表

drop table test.user;

删除schema

drop schema test;

Phoenix索引

初始化,准备Schema与表

create schema test;

create table test.user(
	id INTEGER NOT NULL PRIMARY KEY,
	name VARCHAR,
	age INTEGER
);

全局索引

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

全局索引在默认情况下,如果查询语句中检索的列不在索引表中,Phoenix不会使用索引表,除非使用hint。(全局索引必须是查询语句中所有列都包含在全局索引中,它才会生效)

1.创建索引

CREATE INDEX name_index ON test.user(name);

2.查看索引

!indexes test.user;

+-----------+-------------+------------+------------+-----------------+------------+------+------------------+-------------+-------------+-------------+-------+------------------+-----------+-----------+--+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | NON_UNIQUE | INDEX_QUALIFIER | INDEX_NAME | TYPE | ORDINAL_POSITION | COLUMN_NAME | ASC_OR_DESC | CARDINALITY | PAGES | FILTER_CONDITION | DATA_TYPE | TYPE_NAME |  |
+-----------+-------------+------------+------------+-----------------+------------+------+------------------+-------------+-------------+-------------+-------+------------------+-----------+-----------+--+
|           | TEST        | USER       | true       |                 | NAME_INDEX | 3    | 1                | 0:NAME      | A           |             |       |                  | 12        | VARCHAR   |  |
|           | TEST        | USER       | true       |                 | NAME_INDEX | 3    | 2                | :ID         | A           |             |       |                  | 4         | INTEGER   |  |
+-----------+-------------+------------+------------+-----------------+------------+------+------------------+-------------+-------------+-------------+-------+------------------+-----------+-----------+--+

3.删除索引

DROP INDEX name_index ON test.user;
DROP INDEX IF EXISTS name_index ON test.user;

本地索引

本地索引适合写多读少的场景,或者存储空间有限的场景。

本地索引因索引数据和原数据存储在同一台机器上,避免了网络数据传输的开销,所以更适合写多的场景。

由于无法提前确定数据在哪个Region上,所以在读数据的时候,需要检查每个Region上的数据从而带来一些性能损耗。

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

创建索引

CREATE LOCAL INDEX name_local_index ON test.user(name);

删除索引

DROP INDEX name_local_index ON test.user;
DROP INDEX IF EXISTS name_local_index ON test.user;

覆盖索引

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

select的列和where的列都需要在索引中出现

创建索引

CREATE INDEX name_age_index  ON test.user(name,age) INCLUDE ( id);

查询

 select name,age  from test.user where name ='hbase2' and age=22;

函数索引

函数索引的特点是索引的内容不局限于列,能根据表达式创建索引。适用于查询表时过滤条件是表达式的情况。

如果使用的表达式正好是索引,数据可以直接从这个索引获取,而不需要从数据库获取。

查看数据

 select * from test.user;
+----+--------+-----+
| ID |  NAME  | AGE |
+----+--------+-----+
| 1  | hbase1 | 20  |
| 2  | hbase2 | 22  |
| 3  | hbase3 | 23  |
+----+--------+-----+

创建索引

# substr(s,n,1en): 从字符串s的n位置截取长度为len的子字符串
CREATE INDEX name_index ON test.user(substr(name,6,1)) INCLUDE ( id);

查询

select *  from test.user where substr(name,6,1)='2';
+----+--------+-----+
| ID |  NAME  | AGE |
+----+--------+-----+
| 2  | hbase2 | 22  |
+----+--------+-----+
1 row selected (0.056 seconds)

索引Building

同步索引

CREATE INDEX async_index ON test.user(BASICINFO."s1",BASICINFO."s2");

当创建同步索引超时,修改hbase-site.xml,把超时参数设置大一些,足够 Build 索引数据的时间

<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>

异步索引
异步Build索引需要借助MapReduce,创建异步索引语法和同步索引相差一个关键字:ASYNC。

CREATE INDEX async_index ON test.user ( BASICINFO."s1",BASICINFO."s2" ) ASYNC;

view视图映射hbase中的表

HBase数据准备

创建hbase表

create 'user','info'

插入数据

put 'user','001','info:name','hbase1'
put 'user','001','info:age',11
put 'user','002','info:name','hbase2'
put 'user','002','info:age',22

查看数据

hbase(main):008:0> scan 'user'
ROW                                                  COLUMN+CELL
 001                                                 column=info:age, timestamp=1652001388683, value=11
 001                                                 column=info:name, timestamp=1652001388604, value=hbase1
 002                                                 column=info:age, timestamp=1652001390069, value=22
 002                                                 column=info:name, timestamp=1652001388734, value=hbase2
2 row(s)
Took 0.1370 seconds

创建视图

注意:
1.phoenix区分大小写,不加""会转成大写;

2.通过view映射是只读的;

create view "user"(
id varchar primary key, 
"info"."name" varchar,
"info"."age" varchar );
 select * from "user";
+-----+--------+-----+
| ID  |  name  | age |
+-----+--------+-----+
| 001 | hbase1 | 11  |
| 002 | hbase2 | 22  |
+-----+--------+-----+
2 rows selected (0.061 seconds)

创建索引

create index user_name_index on "user"("info"."name");
select "name" from "user" group by  "name";
+--------+
|  name  |
+--------+
| hbase1 |
| hbase2 |
+--------+
2 rows selected (0.06 seconds)

删除视图

删除视图后,hbase中的表依然存在

 drop view "user";

JDBC

添加依赖

   <dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-core</artifactId>
            <version>5.1.2</version>
        </dependency>

API操作

public class PhoenixTest {

    private static Connection connection = null;
    private static Statement statement = null;

    /**
     * 获取连接
     */
    @Before
    public void init() {
        try {
            Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
            //这里配置zookeeper地址,可单个,也可多个,可以是域名或者ip
            String url = "jdbc:phoenix:112.74.96.150:2181/hbase";
            connection = DriverManager.getConnection(url);
            statement = connection.createStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After
    public void close() throws SQLException {
        statement.close();
        connection.close();
    }

    /**
     * 创建数据表
     *
     * @throws SQLException
     */
    @Test
    public void createTableTest() throws SQLException {
        String sql = "create table tb_test (mykey integer not null primary key,mycolumn varchar)";
        statement.executeUpdate(sql);
        connection.commit();
        System.out.println("创建数据表成功!");
    }

    /**
     * 单条插入数据
     *
     * @throws SQLException
     */
    @Test
    public void upsertTest() throws SQLException {
        String sql1 = "upsert into tb_test values(1,'test1')";
        String sql2 = "upsert into tb_test values(2,'test2')";
        String sql3 = "upsert into tb_test values(3,'test3')";
        statement.executeUpdate(sql1);
        statement.executeUpdate(sql2);
        statement.executeUpdate(sql3);
        connection.commit();
        System.out.println("数据已插入!");
    }

    /**
     * 删除数据
     *
     * @throws SQLException
     */
    @Test
    public void deleteTest() throws SQLException {
        String sql = "delete from tb_test where mykey=3";
        statement.executeUpdate(sql);
        connection.commit();
        System.out.println("删除数据成功!");
    }

    /*检索数据表中的记录*/
    @Test
    public void readAllTest() throws SQLException {
        String sql = "select * from tb_test";
        long time = System.currentTimeMillis();
        ResultSet rs = statement.executeQuery(sql);
        connection.commit();
        while (rs.next()) {
            //获取字段值
            int mykey = rs.getInt("mykey");
            //获取字段值
            String mycolumn = rs.getString("mycolumn");
            System.out.println("mykey:" + mykey + "\t" + "mycolumn:" + mycolumn);
        }
        rs.close();
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136956.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!