Phoenix 5索引

Phoenix5.0 安装部署 搭建了Phoenix环境,及一些简单shell使用,本文介绍一下Phoenix二级索引。

Phoenix二级索引分为全局索引和本地索引

函数索引 Functional Indexes

在4.3及以上的版本中,Phoenix提供了函数索引。
函数索引可以使用函数表达式来创建索引,在查询时,如果使用这个函数表达式查询,则可以使用到索引。

CREATE INDEX UPPER_NAME_IDX ON EMP (UPPER(FIRST_NAME||' '||LAST_NAME))

SELECT EMP_ID FROM EMP WHERE UPPER(FIRST_NAME||' '||LAST_NAME)='JOHN DOE'

全局索引Global Indexes

Global indexing适用于多读少写的业务场景。使用Global indexing的话在写数据的时候会消耗大量开销,因为所有对数据表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),会引起索引表的更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。

配置hbase-site.xml

如果想使用全局索引,需要配置hbase-site.xml:

<property>
    <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>

测试索引

create table company(id varchar primary key, name varchar, address varchar);
--- 查看索引
!indexes company;
-- 创建索引
create index my_index on company(name);
--删除索引表
drop index my_index on company
-- 查看表就会发现多了一张索引表
!tables
SELET * FROM MY_INDEX

-- 插入数据
upsert into company(id, name, address) values('001', 'dimensoft', 'nanjing');
-- 查询数据
select name,address from company where name='dimensoft';

-- 查询索引表MY_INDEX
SELECT * FROM MY_INDEX
或者
scan 'MY_INDEX'


特别注意

select name,address from company where name='dimensoft';这样的查询语句是不会用到索引表的.

Global mutable index will not be used unless all of the columns referenced in the query are contained in the index.

name字段虽然是索引字段但是address字段并不是索引字段!也就是说需要查询出来的字段必须都是索引字段如:
select name from company where name='dimensoft';

如果希望使用索引表进行查询的话可以使用以下三种方式来解决这个问题:

强制使用索引表

SELECT /*+ INDEX(company my_index) */ name,address FROM company WHERE name = 'dimensoft';

This will cause each data row to be retrieved when the index is traversed to find the missing address column value. This hint should only be used if you know that the index has good selective (i.e. a small number of table rows have a value of ‘dimensoft’ in this example), as otherwise you’ll get better performance by the default behavior of doing a full table scan.

这样的查询语句会导致二次检索数据表,第一次检索是去索引表中查找符合name为dimensoft的数据,这时候发现address字段并不在索引字段中,会去company表中第二次扫描,因此只有当用户明确知道符合检索条件的数据较少的时候才适合使用,否则会造成全表扫描,对性能影响较大。

创建覆盖索引 covered index

创建索引的时候指定一个covered字段,先删除my_index索引 drop index my_index on company;
创建covered index: create index my_index on company(name) include(address);

This will cause the address column value to be copied into the index and kept in synch as it changes. This will obviously increase the size of the index.
使用这种方式创建的所有会导致address字段的值被拷贝到索引中,缺点就是会导致索引表大小有一定的增加。

查询索引表my_index数据。select * from my_index;
这个时候就再使用select name,address from company where name='dimensoft';查询语句就会使用到索引来进行查询了。

使用Local Indexing创建索引

与Global Indexing不同,当使用Local Indexing的时候即使查询的所有字段都不在索引字段中时也会用到索引进行查询(这是由Local Indexing自动完成的)

本地索引 Local Indexes

Local indexing targets write heavy, space constrained use cases. Just like with global indexes, Phoenix will automatically select whether or not to use a local index at query-time. With local indexes, index data and table data co-reside on same server preventing any network overhead during writes. Local indexes can be used even when the query isn’t fully covered (i.e. Phoenix automatically retrieve the columns not in the index through point gets against the data table). Unlike global indexes, all local indexes of a table are stored in a single, separate shared table.At read time when the local index is used, every region must be examined for the data as the exact region location of index data cannot be predetermined.Thus some overhead occurs at read-time.
Local indexing适用于写操作频繁的场景。与Global indexing一样,Phoenix会自动判定在进行查询的时候是否使用索引。使用Local indexing时,索引数据和数据表的数据是存放在相同的服务器中的避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。使用Local indexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Global indexing不同。一个数据表的所有索引数据都存储在一个单一的独立的可共享的表中。在使用本地索引的读取时,必须检查每个区域region 的数据,因为不能预先确定索引数据的确切区域位置。因此在读取时发生一些开销。

配置hbase-site.xml

同样需要修改 hbase-site.xml文件,添加以下几个配置:

<property>
  <name>hbase.master.loadbalancer.class</name>
  <value>org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer</value>
</property>
<property>
  <name>hbase.coprocessor.master.classes</name>
  <value>org.apache.phoenix.hbase.index.master.IndexMasterObserver</value>
</property>
<property>
  <name>hbase.coprocessor.regionserver.classes</name>
  <value>org.apache.hadoop.hbase.regionserver.LocalIndexMerger</value>
</property>

The above properties prevent deadlocks from occurring during index maintenance for global indexes (HBase 0.98.4+ and Phoenix 4.3.1+ only) by ensuring index updates are processed with a higher priority than data updates. It also prevents deadlocks by ensuring metadata rpc calls are processed with a higher priority than data rpc calls.
上述属性通过确保以比数据更新更高的优先级处理索引更新来防止在全局索引(HBase 0.98.4+和Phoenix 4.3.1+)的索引维护期间发生死锁。 它还通过确保以比数据rpc调用更高的优先级处理元数据rpc调用来防止死锁。
简而言之就是更新索引的优先级比数据更新和rpc调用的优先级高

创建本地索引

create local index my_index on company(name);

查看当前所有表会发现多一张MY_INDEX索引表,查询该表数据。
在这里插入图片描述
通过squirrel来查看company的索引字段。
在这里插入图片描述
从HBase的CLI界面查看当前所有表。
在这里插入图片描述

这里的索引表并不叫MY_INDEX,而是叫_LOCAL_IDX_COMPANY,但是在Phoenix的CLI中进行数据查询的时候仍然是使用MY_INDEX进行查询,应该是做了映射。

插入数据upsert into company(id, name, address) values('001', 'dimensoft', 'nanjing');
在这里插入图片描述
从HBase的CLI界面查看索引表_LOCAL_IDX_COMPANY。
在这里插入图片描述
3个索引字段_INDEX_ID、NAME和ID的值被合并为索引表的rowKey,其中_INDEX_ID并没有值(\x000是十六进制表示,转换为字符串是空格)。

异步创建索引

一般我们可以使用CREATE INDEX来创建一个索引,这是一种同步的方法。但是有时候我们创建索引的表非常大,我们需要等很长时间。Phoenix 4.5以后有一个异步创建索引的方式,使用关键字ASYNC来创建索引:

CREATE INDEX index1_c ON hao1 (age) INCLUDE(name) ASYNC;
这时候创建的索引表中不会有数据。你还必须要单独的使用命令行工具来执行数据的创建。当语句给执行的时候,后端会启动一个map reduce任务,只有等到这个任务结束,数据都被生成在索引表中后,这个索引才能被使用。启动工具的方法:

${HBASE_HOME}/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool
  --schema MY_SCHEMA --data-table MY_TABLE --index-table ASYNC_IDX
  --output-path ASYNC_IDX_HFILES

这个任务不会因为客户端给关闭而结束,是在后台运行。你可以在指定的文件ASYNC_IDX_HFILES中找到最终实行的结果。

索引重建

有两种方式:

drop index ind on "testTable";
create index ind on "testTable"("ext"."userId");

或者

alter index ind on "testTable" REBUILD;

参考资料

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐崇拜234

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值