Phoenix二级索引

来源:互联网 发布:淘宝店铺会员设置折扣 编辑:程序博客网 时间:2024/06/07 06:43

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

1、Covered Indexes(覆盖索引)
覆盖索引:只需要通过索引就能返回所要查询的数据,所以索引的列必须包含所需查询的列(SELECT的列和WHRER的列)

不同于hbase的Coprocessor机制创建的二级索引表,Phoenix下的二级索引可以是覆盖索引,即把关心的数据和索引项存储在一张表中,这样就减少了一次读表的时间,而后者主要通过查询关键字再查到主键再利用主键查询最终结果。效率上来讲,是phoenix的一半。
用法示例如下:

CREATE INDEX my_index ON my_lin(v1,v2) INCLUDE(v3)

2、Functional indexes(函数索引)
从Phoeinx4.3以上就支持函数索引,其索引不局限于列,可以合适任意的表达式来创建索引,当在查询时用到了这些表达式时就直接返回表达式结果

函数索引不仅允许直接在列上创建索引,还允许通过基于某一列计算值来创建索引。
用法示例如下:

CREATE INDEX UPPER_NAME_IDX ON EMP (UPPER(FIRST_NAME||' '||LAST_NAME))
该用例实现的功能是创建以大小写不敏感的firstname和lastname组合为索引项的索引。
查询示例如下:
SELECT EMP_ID FROM EMP WHERE UPPER(FIRST_NAME||' '||LAST_NAME)='JOHN DOE

3、Global indexes(全局索引)

全局索引适用于多读少写的场景,在写操作上会给性能带来极大的开销,因为所有的更新和写操作(DELETE,UPSERT VALUES和UPSERT SELECT)都会引起索引的更新,在读数据时,Phoenix将通过索引表来达到快速查询的目的。

4、 本地索引

本地索引适用于写任务重、空间受限的情形。与全局索引相同的是,Phoenix在查询时时也会自动判断是否启用本地索引。在本地索引中,索引表和数据表存储在同一个服务器上以防止在写操作执行过程中导致网络过载。即便查询内容不被索引完全覆盖,本地索引也可以使用。与全局索引不同的是,本地索引存储单个、分别共享的表中。在进行读操作时,由于该索引表的精确域不能预先确定,每一个区域都必须检查自身的数据。这样就有可能导致网络过载。

Global Indexing v.s. Local Indexing

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.

Local Indexing

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.

重点标记:在实际使用过程中不建议使用phoenix的二级索引,特别是那种需要经常进行插入操作的场景,为什么不建议呢?这是笔者生产的教训,我们使用phoenix来存储strom实时清洗出来的数据,发现整个hbase每隔几天就会挂掉,后面才排查出就是二级索引的鬼?为什么呢?想想吧,一张几亿数据量的表,你在进行插入操作的时候,就是重新构建索引表,如果这时你又刚好用这二级索引进行查询操作,而且也是经常的,那会导致什么?没错,数据在转移时会发生动荡,一般那个进行查询的机器会挂掉,然后它这台机器的数据会发生转移,然后你又查询,又可能导致更多的机器挂掉。这里最好的方法应该是尽量走rowkey查询,这是一个血的教训!phoenix还是只适合实时的大批量插入操作,而涉及到非rowkey查询一定要小心,同理,Hbase也是的。

还有以下几个坑,如果查询的语句包含了非二级索引列,并且有为null的情况,那么还是会全表扫描的。如果包含了非二级索引列,那还要自己主动强制使用二级索引来查询