phoenix:Secondary Indexing

本文详细探讨了Apache Phoenix中的各种索引类型,包括二级索引、覆盖索引、功能索引、全局索引和本地索引的特点及使用场景。解析了索引创建、查询优化、一致性保证以及事务表和不可变表的索引策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Secondary Indexing


    二级索引是以一种垂直的方式去访问主表的数据(以前是通过get scan去获取数据的)。在Hbase中,有一个独特的索引,主表的row key,按照字典顺序进行排列 。访问数据的方式不再是通过主表的row key(潜在需要进行值全表扫描)去匹配过滤条件。对于二级索引,你索引的表或者表达式构成了 row key来实现点查询和范围查询。

Convered Index
不需要去主表查询,一旦能在索引表中查询到。通过把关心的数据放在索引列的右边,保存加重了读取
CREATE INDEX my_index ON my_table (v1,v2) INCLUDE(v3);
这种方式就能避免去主表获取v3的数据

Functional Indexs 4.3或者以上有效
索引的人创建不再仅仅是基于列,也可以基于一个表达式。然后当一个查询也采用这个表达式时,索引用于获取结果,而不是主表。
创建
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
多读场景 -- 对于全局索引,索引的所有执行消耗出现在写索引上。拦截主表上的写操作(DELETE,UPSERT VALUES,and UPSERT SELECT),建立索引更新,然后发送任务必要的更新至所有相关的索引表。在读数据时,Phoenix挑选能最快查询时间索引表,然后直接获取索引表。默认情况下,查询的列不是索引中的表,将不使用索引,除非使用hint

Local Indexes
多写场景 空间约束-- 如全局索引一样,Phoenix判断在一个查询中是否采用本地索引。对于本地索引,索引数据和主表放在相同的Server -- 避免在写操作网络消耗。即使查询没有全部覆盖,本地索引能够使用。与全局索引不同的是。所有的主表的本地索引有存储在单独的,可分割的,共享表在4.8.0版本前,4.8.0之后,所有的索引数据存储在主表的可分割的,影子 column Family(列族)中。当读取数据时,本地索引是被使用的,每一个region必须查询数据,因为索引数据的位置不能预先知道。因此在读取数据时,出现了很多消耗。

Index Population
默认情况下,当一个表创建时,在CREATE INDEX 调用期间同步创建索引表。索引的创建并不是一定,取决于当前数据表的大小。在4.5版本中,索引的创建可以不是同步的,通过添加ASYNC字段
CREATE INDEX async_index ON my_schema.my_table (v) ASYNC
启动mapReduce job
${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 #指定hdfs目录
 当map reduce job完成,索引将被激活,能被查询调用。The job is resilient to the client being exited.

Index Usage
Phoenix自动使用索引去服务查询,当能有效提高查询效率。然而,全局索引不会使用,除非所有在查询中的相关的行引用都包含在索引中。
SELECT v2 FROM my_table WHERE v1 = 'foo'  -- 没有使用索引
使用索引
方式一
CREATE INDEX my_index on my_table(v1) INCLUDE(v2)
方式二
SELECT /*+ INDEX(my_table my_index)*/ v2 FROM my_table WHERE v1 = 'foo'
方式三
CREATE LOCAL INDEX my_index on my_table(v1)

Drop index
DROP INDEX my_index on my_table
如果主表中的索引的列被删除索引也就被删除。另外,如果主表中的索引表被删除,索引也自动被删除

Index properties
像创建 CREATE TABLE statement,CREATE INDEX statement 设置一些属性应用到Hbase表,包括设置salt。
CREATE INDEX my_index on my_table(v2 DESC,v1) INCLUDE(v3) SALT_BUCKETS=10,DATA_BLOCK_ENCODING='NONE' 或者 'FAST_DIFF'
* 如果 原始表(primary table) 是设置了salt,也自动以相同的方式为index设置salt的全局索引。相对主表和索引表的大小,索引文件MAX_FILESIZE的下调。local index,是不允许指定SALT_BUCKETS

Consistency Guarantees
索引更新是同步的,通过Hbase保证数据的强一致性。然而,因为索引存储在单独的表而不是数据表,由表的属性和所有的类型决定,在主表和索引的变化保存一致由于服务端崩溃导致commit失败。需求和使用场景影响设计。

Transactional Tables
定义事务表,是最高等级保证主表与索引一致性。在这种情况下,提交表的变动和相关的索引是原子性的。如果提交失败,主表与索引都会不更新,因此保证了主表与索引总是同步的。
创建事务表 CREATE TABLE my_table (k BIGINT PRIMARY KEY, v VARCHAR) TRANSACTIONAL=true;把保证table,index更新的一致性,同步更新。
为什么不都定义为Transaction Table,原因:例如 immutable table,事物消耗是很小的。如果你的数据是可变的,确信相关冲突检查的消耗--事物表与运行消耗,事务管理是可被接受的。另外,有二级索引的事物表,潜在降低去写主表的能力,因为主表和二级索引必须是同时可用,否则失败

Immutable Tables 
如果表的数据只是写入,不进行更新,主要的优化是减少增量写的时间开销。通常时序数据,如日志,event data,数据写入,不会进行更新。为了利用这个优点,定义表为immutable
CREATE TABLE my_table(k VARCHAR PRIMAR KEY,v VARCHAR) IMMUTABLE_ROWS=true;
在Immutable上的所有索引都是设置为immutable(默认,表设置为mutable)。对于全局immutable index,在客户端的索引表进行维护的,当有数据进行改变时。不相同的是,本地immutable索引,会在本地进行维护。注意如果强制一个immutable存储mutable数据,这个索引将不再与表同步,
转换immutable index成为mutable index, AlTER TABLE my_table SET IMMUTABLE_ROWS=false
索引在无事务的条件时,immutable table没有机制去自动处理commit failure。维护主表与索引表的一致性通过客户端处理。因为更新数据是幂等性的,最简单的解决方式是,客户端持续的重试批量的变动,直到成功

Mutable Tables
对于非事物mutable table,索引的维护间隔通过更新到主表的WAL中。只有在WAL成功同步到磁盘,再去更新索引和主表。默认索引是并行更新的,引进很高的吞吐量。当正在进行索引更新时,如果服务器崩溃,在WAL恢复程序中,将重新所有的索引到索引表并且依靠幂等性去保存正确性。因此,索引对于非事务mutable table来说,仅是一个单批次的编辑在主表后
以下几个点是很重要的:
1、对于非事务表,索引表与主表是不同步的。
2、是小批量,短时间不同步的。
3、主表的每一行和索引表的每一行,是保证被写和丢失的。
4、数据首先被写入到主表,然后再写入到索引表。通过关闭WAL,使执行顺序相反

Singular Write Path
一个保存故障写入的路径。所有的写入到HRegion被Coprocessor拦截。然后基于即将更新建立索引更新(或者批量更新)。原始更新被追加到WAL。如果目前为此有任何失败,返回错到客户端,数据不会持久化,或者能被客户端查询。
一旦写入到WAL,index和primary数据将变得可被查看,甚至在失败的情况下。
如果服务器崩溃,通过能用的WAL恢复来恢复索引更新。
如果服务器没有崩溃,只需要插入索引更新至各自的表中。
	如果索引更新失败,通过以下方式保证数据一致性
	1.Disallow table writes until mutable index is consistent
	是这最高等级的维护非事务表与索引一致性,是去定义主表更新是临时的、不被允许的事件当更新索引失败时。在这种一致性的模式下,在失败出现前,主表和索引保存在时间戳中,对于主表的写入也是不允许的,直到索引上线并且在主表在同步列表中。
	phoenix.index.failure.block.write = true  -- 开启主表的写,在commit失败事件中,直到索引能跟上主表(同步更新中)
	phoenix.index.failure.handling.rebuild = true  -- 开启mutable重建在commit 失败后
	
	2.Disable mutable indexes on write failure until consistency restored
	如果在写index时commit 失败,对于mutable 索引的默认行为,标记index为不可用,在后台重建索引,然后一旦恢复一致性。再次标记为激活。这种一致性模式,当二级索引重建时,主表的写入是不被阻塞的。二级索引不能被使用在重建时。
	phoenix.index.failure.handling.rebuild = true
	phoenix.index.failure.handling.interval = 
	phoenix.index.failure.hadnling.rebuild.overlap.time = 

	3.Disable mutable index on write failure with manual rebuild required
	这是mutable 二级索引的最低等级的一致性。在这种情况下,当一个二级索引写失败时,索引表标记为不可用,通过手动重建索引,然后通过一个查询使能索引可用
	phoenix.index.failure.handling.rebuild = false 

BulkLoad Tool Limittation
BulkLoadTool(CSVBulkLoadTool 和 JSONBulkLoadTool)不能马上生成正对mutable的二级索引正确更新,当一个已经存在的记录去更新时。在mutable 二级索引写入路径中,phoenix能安全为二级索引计算 Delete(老记录)和Put(新记录) 通过保持一个行锁来避免当前更新。在MapReduce job中,phoenix不能有效的执行相同的逻辑,因为phoenix正在指定实现 'out of band' 从Hbase RegionServers。正因为如此,当这些工具为索引表生成HFile时,需要对正在更新的数据进行相应的更新,任何与先前索引记录相同的是不能被删除。这影响是:如果把相同记录写入到索引表,索引表将有重复记录,将引起错误的查询结果。
	
Set 
Non transactional ,mutabel indexing,在hbase-site.xml
<property>
  <name>hbase.regionserver.wal.codec</name>
  <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>
<property>
  <name>hbase.region.server.rpc.scheduler.factory.class</name>
  <value>org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory</value>
  <description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<property>
  <name>hbase.rpc.controllerfactory.class</name>
  <value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value>
  <description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description>
</property>
<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>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值