Hbase只能基于字典序的rowKey索引,对于非主键过滤条件的查询都会变成扫全表操作,为了解决这个问题Phoenix引入了二级索引功能。然而此二级索引又有别于传统关系型数据库的二级索引。
说明:对于腾讯云EMR,在我们用时,当时创建本地索引,系统提示异常,后面腾讯同事建议不用本地索引,而是用全局索引。目前是否已经完善,大家可以用的时候注意一下。
1、创建测试表
CREATE TABLE IF NOT EXISTS test_user (
id VARCHAR NOT NULL PRIMARY KEY,
username VARCHAR ,
phoen VARCHAR ,
addr VARCHAR,
times bigint) COLUMN_ENCODED_BYTES=0;
UPSERT into test_user(id,username,phoen,addr,times) values('1001','liqinqin','13580501872','广州',10);
UPSERT into test_user(id,username,phoen,addr,times) values('1002','zhans','13580503452','深圳',2);
注意:PHoenix创建表时,在hbase中显示的列名是经过转码的,这里可以通过设置COLUMN_ENCODED_BYTES=0,指明phoenix创建表时,生成的hbase中的列名同phoenix中的列表一致。
2、创建全局索引
CREATE INDEX idx_phoen_test_user ON test_user(phoen);
全局索引更多的应用在读多的场景。它会在hbase中单独创建一条表。
重点:对于全局索引,在查询中检索的列如果不在索引表中,查询将不会走索引,除非使用hint。
通过hbase shell我们看看索引表结构。索引表的rowkey存储了索引列的值和原表RowKey的值,这样就更有利于提高查询性能了
2.1、索引数据结构
SALT BYTE | SALE NUMBER | VIEW INDEX ID | TENANT_ID | INDEX VALUE | ROWKEY |
1)SALT BYTE: 此byte正是存储着salt。全局索引表和普通phoenix表一样,可以在创建索引时指定SALT_BUCKETS或者split key。
3)TENANT_ID: 当前数据对应的多租户ID。
4)INDEX VALUE: 索引数据。
5)PK VALUE: 原表的RowKey。
3、创建本地索引
create local index idx_phoen_test_user ON test_user(phoen);
本地索引很大一个不同时,本地索引和原数据存储在同一个表中,所以更适合写多的场景。对于本地索引不管是否指定hint或查询的列是否都在索引表中,都会用索引表。
通过Hbase shell可以看到,在表中增加了一行数据: column=L#0:_0的索引数据
3.1、本地索引数据结构
REGION START KEY | SALT NUMBER | VIEW INDEX ID | TENANT ID | INDEX VALUE | ROWKEY |
1)REGION START KEY : 当前row所在region的start key。加上这个start key的好处是,可以让索引数据和原数据尽量在同一个region, 减小IO,提升性能。
2)INDEX ID : 每个ID对应不同的索引表。
3)TENANT ID :当前数据对应的多租户ID。
4)INDEX VALUE: 索引数据。
5)PK VALUE: 原表的RowKey。
4、覆盖索引
create index idx_phoen_test_user_cover on test_user(phoen) include(username);
覆盖索引的特点是把原数据存储在索引数据表中,这样在查询到索引数据时就不需要再次返回到原表查询,可以直接拿到查询结果。
通过HBASE SHELL 查询表IDX_PHOEN_TEST_USER_COVER, 我们发现include的列的值被写入到了value中。
当我们用下面的语句查询数据时,可以看是走了索引的
select username,phoen from test_user where phoen='13580501872';
重点:在我们实际应用中一个数据表会有多个索引表,为了能让我们的查询使用合理的索引表,目前都需要通过Hint去指定。
4、构建索引
Phoenix创建二级索引分同步和异常2种方式
1)同步索引 CREATE INDEX idx_phoen_test_user ON test_user(phoen)。此方法适用于数据量较小的情况。
2)异步构建索引需要借助MR,创建异步索引语法和同步索引相差一个关键字:ASYNC
//创建异步索引
CREATE INDEX 索引名 ON DB.表名 (列名) ASYNC
//build 索引数据
${HBASE_HOME}/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool --schema 库名 --data-table 表名--index-table 索引名 --output-path ASYNC_IDX_HFILES
5、索引创建问题
1)创建同步索引超时:修改phoenix目录下的bin下的hbase-site.xml文件,增加或修改下面的参数值
<property>
<name>hbase.rpc.timeout</name>
<value>60000000</value>
</property>
<property>
<name>phoenix.query.timeoutMs</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>
2)索引表最多不超过10个,索引越多,将影响数据的写入。
对于索引,phoenix还提供了函数索引,这里不展开,可自行学习