Phoenix 二级索引之— —Global Indexing

1. 说明


Hbase中,只有一个单一的按照字典序排序的rowKey索引,当使用rowKey来进行数据查询的时候速度较快,但是如果不使用rowKey来查询的话就会使用filter来对全表进行扫描,很大程度上降低了检索性能。而Phoenix提供了二级索引技术来应对这种使用rowKey之外的条件进行检索的场景。

Phoenix支持两种类型的索引技术:Global Indexing和Local Indexing,这两种索引技术分别适用于不同的业务场景(主要是偏重于读还是偏重于写)。下面分别对这两种索引技术简单使用一下,具体性能方面没有进行测试

以上文字摘自官方文档

http://phoenix.apache.org/secondary_indexing.html

本篇主要介绍Global Indexing相关技术。 

2. Global Indexing


Global indexing targets read heavy,low write uses cases. With global indexes, all the performance penalties for indexes occur at write time. We intercept the data table updates on write (DELETE, UPSERT VALUES and UPSERT SELECT), build the index update and then sent any necessary updates to all interested index tables. At read time, Phoenix will select the index table to use that will produce the fastest query time and directly scan it just like any other HBase table. By default, unless hinted, an index will not be used for a query that references a column that isn’t part of the index.

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


2.1 配置hbase-site.xml


使用Global Indexing的话需要配置hbase-site.xml,在HBase集群的每个regionserver节点的hbase-site.xml中加入如下配置并重启HBase集群

<property>
    <name>hbase.regionserver.wal.codec</name>
    <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4


2.2 创建表


进入phoenix的CLI的界面创建company表。

> create table company(id varchar primary key, name varchar, address varchar);
 
 
  • 1
  • 1

这里写图片描述

查看company表索引

> !indexes company
 
 
  • 1
  • 1

这里写图片描述


2.3 创建索引


对company表的name字段创建索引,索引名为my_index。

> create index my_index on company(name);
 
 
  • 1
  • 1

查看当前所有表会发现多一张MY_INDEX索引表,查询该表数据。

> !tables
> select * from my_index;
 
 
  • 1
  • 2
  • 1
  • 2

这里写图片描述

该表中会有2个字段,其中:ID是自动创建的,其实就是HBase中的主键RowKey,0:NAME是我们刚刚手动创建的。


2.4 插入数据


在company表中添加测试数据。

> upsert into company(id, name, address) values('001', 'dimensoft', 'nanjing');
 
 
  • 1
  • 1


2.5 查询数据


查询company表数据

> select name,address from company where name='dimensoft';
 
 
  • 1
  • 1

这里写图片描述

查询索引表my_index

> select * from my_index;
 
 
  • 1
  • 1

这里写图片描述

从HBase的CLI界面查看索引表MY_INDEX

> scan 'MY_INDEX'
 
 
  • 1
  • 1

这里写图片描述

2个索引字段NAME和ID的值被合并为索引表MY_INDEX的rowKey,\x000是十六进制表示,转换为字符串是空格。

高能预警:

> select name,address from company where name='dimensoft';
 
 
  • 1
  • 1

这样的查询语句是不会用到索引表的

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';
 
 
  • 1
  • 1

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

  • 强制使用索引表

在进行查询的时候通过sql语句强制使用索引查询。

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

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;
 
 
  • 1
  • 1

创建covered index

> create index my_index on company(name) include(address);
 
 
  • 1
  • 1

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;
 
 
  • 1
  • 1

这里写图片描述

这里的数据是自动同步过来的,可以发现address字段的值也被存储了。

从HBase的CLI中查看MY_INDEX表数据会发现比不使用include的时候多了一行数值,并且里面包含了address字段的值。

> scan 'MY_INDEX'
 
 
  • 1
  • 1

这里写图片描述

这个时候就再使用下面的查询语句就会使用到索引来进行查询了。

> select name,address from company where name='dimensoft';
 
 
  • 1
  • 1
  • 使用Local Indexing创建索引

与Global Indexing不同,当使用Local Indexing的时候即使查询的所有字段都不在索引字段中时也会用到索引进行查询(这是由Local Indexing自动完成的)。这部分内容会放到后一篇文章详细介绍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值