1、Phoenix
Phoenix 是 HBase 的开源 SQL 皮肤。可以使用标准 JDBC API 代替 HBase 客户端 API 来创建表,插入数据和查询 HBase 数据。
启动 phoenix:
/opt/module/phoenix/bin/sqlline.py hadoop102,hadoop103,hadoop104:2181
1.1、Phoenix Shell 操作
1.1.1、table 操作
查看所有表
语法:!table 或者 !tables
创建表
注意:
- 创建表时必须指定 row key(这里是主键)
- phoenix 创建的表名会自动转为大写,如果要小写,使用双引号
CREATE TABLE IF EXISTS student(
id VARCHAR primary key,
name VARCHAR,
age BIGINT,
addr VARCHAR);
也可以指定多个 rowkey:
CREATE TABLE IF NOT EXISTS student (
id VARCHAR NOT NULL,
name VARCHAR NOT NULL,
age BIGINT,
addr VARCHAR
CONSTRAINT my_pk PRIMARY KEY (id, name));
注:Phoenix 中建表,会在 HBase 中创建一张对应的表。为了减少数据对磁盘空间的占 用,Phoenix 默认会对 HBase 中的列名做编码处理。具体规则可参考官网链接,若不想对列名编码,可在建表语句末尾加 上 COLUMN_ENCODED_BYTES = 0;
从官网可以看到,使用数字编码作为列名, 如果使用两个字节的数字(默认是 2),那么最多可以表示 65535 个列(相当于 Java short 类型),对于动辄存储几十亿行数据的 HBase 来说,缩短列名能够节省很大的空间。如果不希望使用这个配置直接在建表语句后面添加 COLUMN_ENCODED_BYTES=0 即可。
插入数据
upsert into student values ('1001','zhangsan',23,'shanghai');
插入结果:
删除数据
delete from student where id='1001';
删除表
drop table student;
退出命令行
!quit
1.1.2、表的映射
默认情况下, HBase 中已存在的表,通过 Phoenix 是不可见的。如果要在 Phoenix 中操作 HBase 中已存在的表,可以在 Phoenix 中进行表的映射。映射方式有两种:视图映射和表映射。
视图映射
Phoenix 创建的视图是只读的,所以只能用来做查询,无法通过视图对数据进行修改等操作。
注意:带有 namespace 的表需要专门处理,不能直接配置表映射!
创建映射时,每一个列都必须和映射对应上!
删除映射
注意:
- 映射名加引号!
- 删除映射并不会把数据删除掉;
drop view "view_name";
表映射
在 Pheonix 创建表去映射 HBase 中已经存在的表,是可以修改删除 HBase 中已经存在的数据的。而且,删除 Phoenix 中的表,那么 HBase 中被映射的表也会被删除。
注意:
- 进行表映射时,不能使用列名编码,需将 column_encoded_bytes 设为 0。
- 创建表映射时,phoenix 中不能存在同名的表映射(包括视图映射)
- 删除表映射要谨慎,会删除 hbase 对应表的数据!
1.1.3、数字类型
HBase 中的数字,底层存储为补码,而 Phoenix 中的数字,底层存储为在补码的基础上, 将符号位反转。故当在 Phoenix 中建表去映射 HBase 中已存在的表,当 HBase 中有数字类型 的字段时,会出现解析错误的现象。
解决方案:
- Phoenix 种提供了 unsigned_int,unsigned_long 等无符号类型,其对数字的编码解码方式和 HBase 是相同的,如果无需考虑负数,那在 Phoenix 中建表时采用无符号类型是最合适的选择。
create view "test_number"(
id varchar primary key,
"info"."number" unsigned_long -- 使用无符号数值类型
);
- 如需考虑负数的情况,则可通过 Phoenix 自定义函数,将数字类型的最高位,即 符号位反转即可,自定义函数可参考官网。
1.2、Phoenix 二级索引
添加如下配置到每个 RegionServer 节点的 hbase-site.xml:
<!-- phoenix regionserver 配置参数-->
<property>
<name>hbase.regionserver.wal.codec</name>
<value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
1.2.1、全局索引
Global Index 是默认的索引格式,创建全局索引时,会在 HBase 中建立一张新表(索引表)。也就 是说索引数据和数据表是存放在不同的表中的,因此全局索引适用于多读少写的业务场景。 写数据的时候会消耗大量开销,因为索引表也要更新,而索引表是分布在不同的数据节 点上的,跨节点的数据传输带来了较大的性能消耗。
在读数据的时候 Phoenix 会选择索引表来降低查询消耗的时间。
和我们 MySQL 中的索引一样,原表修改之后,索引表当然也要修改,不然查出来的数据都是错的;
创建单个字段的全局索引:
创建索引的语法和 MySQL 一样:
可以看到,phoenix 中多了一张全局索引表;
使用索引:
删除索引:
全局索引的问题:
即使我们的过滤条件字段是全局索引,但是因为查询字段中除了主键还包含非索引字段,所以索引不会命中,依然会全表扫描,性能比较低; 这种情况我们一般使用包含索引来解决:
1.2.2、包含索引
创建携带其他字段的全局索引(本质还是全局索引)
CREATE INDEX my_index ON my_table (v1) INCLUDE (v2);
1.2.3、本地索引
Local Index 适用于写操作频繁的场景。
索引数据和数据表的数据是存放在同一张表中(且是同一个 Region),避免了在写操作 的时候往不同服务器的索引表中写索引带来的额外开销。
my_column 可以是多个。
CREATE LOCAL INDEX my_index ON my_table (my_column...);
本地索引会将所有的信息存在一个影子列族中,虽然读取的时候也是范围扫描,但是没有全局索引快,优点在于不用写多个表了;
前面的全局索引和包含索引的索引表是保存在集群中专门的表中的,而本地索引是会写入到当前表的一个列族当中(也叫影子列族),这是它们的一个区别点;