2022-09-07 Phoenix Shell操作、API操作、二级索引

当使用Phoenix作为客户端去操作HBase时,Phoenix中执行DDL语句中的namespace名称、表名称、字段名称等等默认都会被转换成大写,如果想要其维持小写形式,需要使用双引号("")括住。

Phoenix实际上是HBase客户端的一个皮肤,其支持标准SQL语法。

官方SQL语法文档,往下翻阅到最后:REFERENCE一栏

一、Shell操作

1. 帮助命令

# 显示出可以使用的Phoenix命令
!help

2. 展示所有创建的表

!tables

3. 创建schema(即namespace或者数据库)

CREATE SCHEMA [IF NOT EXISTS] schema_name;

4. 切换当前工作schema

USE schema_name;

5. 创建表

表中字段类型

-- 建表的时候,指定单一主键
CREATE TABLE IF NOT EXISTS my_schema.my_table (
	field_name1 type PRIMARY KEY,
	field_name2 type,
	...
)


-- 建表的时候指定联合主键:
CREATE TABLE IF NOT EXISTS my_schema.my_table (
	field_name1 type,
	field_name2 type,
	...
	CONSTRAINT pk_name PRIMARY KEY (field_name, ...) 
)

-- 无论是单一主键、还是联合主键,在HBase中都体现为Row Key



-- 为了节约HBase底层存储表中字段的存储空间,Phoenix默认会在创建表的时候,对表中每个
-- 字段进行编码,将编码后的内容实际存储到HFile中,因此会出现这样一种现象:
-- 在HBase原生客户端中使用scan命令查看数据,会发现列名由十六进制编码组成,
-- 如果不想让Phoenix将表中字段编码后放进HFile中,可以如下书写建表语句:
create_table_statement
COLUMN_ENCODED_BYTES = NONE;
-- 详细内容参考:https://phoenix.apache.org/columnencoding.html



-- 值问题:对于VARCHAR、CHAR、无符号数值类型,Phoenix会直接套用HBase的处理逻辑;
-- 但是对于有符号数值类型,Phoenix有自己的处理方案,这就会导致Phoenix无法正确
-- 读取HBase中的有符号数值类型,Hbase也无法正确读取Phoenix中的有符号数值类型

6. 插入\修改数据

UPSERT INTO [schema_name.]table_name [(field_name1, field_name2, ...)] VALUES (value1, value2, ...), ...;

7. 删除数据

DELETE FROM [schema_name.]table_name [WHERE condition];

8. 视图映射(HBase中已经存在表,但是Phoenix中不存在,视图是只读的)

--  PRIMARY KEY的命名随意,它充当HBase中的Row Key

CREATE VIEW "[namespace_name_in_hbase.]table_name_in_hbase" 
(
    id VARCHAR PRIMARY KEY, 
    "column_family_name_in_hbase"."column_name_in_hbase" type,
    ...
) ;

9. 表映射(HBase中已经存在表,但是Phoenix中不存在)

--  PRIMARY KEY的命名随意,它充当HBase中的Row Key

CREATE TABLE "[namespace_name_in_hbase.]table_name_in_hbase" 
(
    id VARCHAR PRIMARY KEY, 
    "column_family_name_in_hbase"."column_name_in_hbase" type,
    ...
) 
COLUMN_ENCODED_BYTES = NONE;

10. 删除表

DROP TABLE [IF EXISTS] [schema_name.]table_name;

11. 查询(SELECT)

和标准SQL对比起来,不能说完全一样,简直是如出一辙。

二、API操作

由于Phoenix遵守了标准SQL规范,其操作流程完全符合普通JDBC API的使用,唯一不同的仅仅在于:获取连接对象的方法有些改动、某些SQL语句需要符合Phoenix的语法。

What is the Phoenix JDBC URL syntax?

1. 获取胖客户端连接对象

(1) 添加依赖

        <dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-core</artifactId>
            <version>5.0.0-HBase-2.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish</groupId>
                    <artifactId>javax.el</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.el</artifactId>
            <version>3.0.1-b06</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.8.4</version>
            <scope>provided</scope>
        </dependency>

(2) 获取

        // 后面的主机名是zookeeper所在机器主机名,端口号是2181
        String jdbcURL = "jdbc:phoenix:hadoop101,hadoop102,hadoop103:2181";
        Properties properties = new Properties();
        properties.put("phoenix.schema.isNamespaceMappingEnabled", "true");
        Connection connection = DriverManager.getConnection(jdbcURL, properties);

2. 获取瘦客户端连接对象

(1) 添加依赖

        <dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-queryserver-client</artifactId>
            <version>5.0.0-HBase-2.0</version>
        </dependency>

(2) 获取

        // 主机名是query server所在的机器主机名,默认端口号为8765
        String jdbcURL = ThinClientUtil.getConnectionUrl("hadoop101", 8765);
        Connection connection = DriverManager.getConnection(jdbcURL);

3. 基操

        String sql = "select * from TEST1.user1";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        String outputForamt = "id: {0}, name: {1}, age: {2}";
        while (resultSet.next()){
            String id = resultSet.getString("id");
            String name = resultSet.getString("name");
            Integer age = resultSet.getInt("age");
            System.out.println(MessageFormat.format(outputForamt, id, name, age));
        }

        resultSet.close();
        preparedStatement.close();
        connection.close();

三、Phoenix二级索引

1. 配置二级索引

添加如下配置到HBaseRegionserver节点的hbase-site.xml

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

# 任意一台机器上配置,然后分发
vim $HBASE_HOME/conf/hbase-site.xml
xrsync.sh $HBASE_HOME/conf/hbase-site.xml

2. 全局索引

(1) 语法

# 为其他列建立索引
# INCLUDE后包含的列并不建索引,作为一个普通列加入索引表中,
# 从而可以实现直接从索引表中查出数据,不需要跑到整张表中查询数据
CREATE INDEX index_name on table_name(column1, column2, ...) [INCLUDE (column3, column4, ...)]

# 什么情况下从索引表中查询数据?
# (1) 过滤条件使用row key,单点查询,效率最高
# (2) 如果索引表中不包含普通列,要求查询语句中出现的所有列必须是row key以及建立了索引的列,
# 同时要求条件中列的顺序为:[row key] 声明索引时指定的第一列 声明索引时指定的第二列 ...
# 不可以不连续。特别的,如果条件中出现了所有索引列,可以不按顺序书写,Phoenix会进行优化,
# 将其重新排序
# (3) 使用了INCLUDE,此时查询语句放宽了限制,可以有在索引表中的普通列,其他相对于(2)情况不变

(2) 实现方式

当在Phoenix中建好了一张表后,只有建表时标记为primary key的列会作为HBase中的row key,这样就导致:根据row key进行查询,效率非常高,但是根据其他列查询,只会是全表扫描。

当为某一列(或者组合多列)建好索引索引后,会将这些列和row key拿出来,同时PhoenixHBase中新建一张索引表,Phoenix中索引表的结构为各个列组成,列的顺序就是建索引的时候书写的列的顺序;HBase底层中表示为索引的列+row key组合为一个row key

3. 本地索引

(1) 语法

# 为其他列建立本地索引
CREATE LOCAL INDEX index_name on table_name(column1, column2, ...)

# 什么情况下根据索引查询数据?
# (1) 过滤条件使用row key,单点查询,效率最高
# (2) 要求查询语句中出现的所有列必须是row key以及建立了索引的列,
# 同时要求条件中列的顺序为:[row key] 声明索引时指定的第一列 声明索引时指定的第二列 ...
# 不可以不连续。特别的,如果条件中出现了所有索引列,可以不按顺序书写,Phoenix会进行优化,
# 将其重新排序

(2) 实现

Phoenix中基本一样,但在HBase底层存储上,不会新建一张表用来单独存储索引,而是会将索引内容直接放入原表中与全数据一起维护。

4. 查看查询语句的执行计划

EXPLAIN select_statement

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值