Phoenix的二级索引(1)

Phoenix使用HBase作为后端存储,对于HBase来说,我们通常使用字典序的RowKey来快速访问数据,除此之外,也可以使用自定义的Filter来搜索数据,但是它是基于全表扫描的。而Phoenix提供的二级索引是可以避开全表扫描,是在HBase中快速查找或批量检索数据的另一个选择。下面的例子使用如下表进行测试:

CREATE TABLE HAO1  ( id char(36) not null primary key, name varchar(50), age INTEGER, createtime DATE)

本文的SQL Client是SQuirrel 3.7.1。

覆盖索引 Covered Indexes

Phoenix提供了一种叫Covered Index覆盖索引的二级索引。这种索引在获取数据的过程中,内部不需要再去HBase上获取任何数据,你查询需要返回的列的数据都会被存储在索引中。要想达到这种效果,你的select 的列,where 的列都需要在索引中出现。举个例子,如果你的SQL语句是 select name from hao1 where age=2,要最大化查询效率和速度最快,你就需要建立覆盖索引:

CREATE INDEX index1_c ON hao1 (age) INCLUDE(name);

注意关键字INCLUDE,就是包含需要返回数据结果的列。这种索引方式的最大好处就是速度快,而我们也知道,索引就是空间换时间,所以缺点也很明显,存储空间耗费较多。Phoenix的索引其实就是建了一张HBase的表。你可以通过HBase Shell的list命令看到。查看表index1_c,你会发现,这张表一共三列,一列就是索引,第二列是RowKey,最后一列就是Name的值。很明显在这里记录的RowKey,就是为了快速查找HBase中的数据。只是这里用不到,Name已经被缓存在这张索引里面了,直接返回。

我们来看一下执行计划,首先看一下没有查询条件的计划,如下图,是一个全表扫描的计划:

而加了索引以后,就是下图这样。很明显,已经是Range Scan,使用到了索引INDEX1_C。

但要注意的是,如果是 select * from hao1 where age =2 的话,还是会看原数据表,只是使用RowKey去访问了,效率自然没有直接从索引表中回去。因为select 的其他列不在索引表内。

函数索引 Functional Indexes

函数索引从4.3版本就有,这种索引的内容不局限于列,还能在表达式上建立索引。如果你使用的表达式正好就是索引的话,数据也可以直接从这个索引获取,而不需要从数据库获取。比如说,在一个表达式上建立索引,这个表达式是UPPER(name) || ‘_test‘:

CREATE INDEX index2_f ON hao1 (UPPER(name) || ‘_test‘);

同样的index2_f表会被建立,里面存储了表达式求值后的结果,和RowKey的关系。当然也可以添加INCLUDE作为覆盖索引,做了覆盖索引,就不需要再去原数据表中获取数据。但是数据会多很多。

在索引范围上,Phoenix的索引可以分为全局索引和本地索引,两种索引适合的场景不同。

全局索引 Global Indexes

全局索引适合那些读多写少的场景。如果使用全局索引,读数据基本不损耗性能,所有的性能损耗都来源于写数据。数据表的添加、删除和修改都会更新相关的索引表(数据删除了,索引表中的数据也会删除;数据增加了,索引表的数据也会增加)。而查询数据的时候,Phoenix会通过索引表来快速低损耗的获取数据。默认情况下,如果你的查询语句中没有索引相关的列的时候,Phoenix不会使用索引。

本地索引 Local Indexes

本地索引适合那些写多读少,或者存储空间有限的场景。和全局索引一样,Phoenix也会在查询的时候自动选择是否使用本地索引。本地索引之所以是本地,只要是因为索引数据和真实数据存储在同一台机器上,这样做主要是为了避免网络数据传输的开销。如果你的查询条件没有完全覆盖索引列,本地索引还是可以生效。因为无法提前确定数据在哪个Region上,所以在读数据的时候,还需要检查每个Region上的数据而带来一些性能损耗。

如下示例,创建了本地索引,然后查看了索引表的数据。

CREATE LOCAL INDEX index3_l_name ON hao1 (name);

异步创建索引

一般我们可以使用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中找到最终实行的结果。

 

索引的使用

索引定义完之后,一般来说,Phoenix会判定使用哪个索引更加有效。但是,全局索引必须是查询语句中所有列都包含在全局索引中,它才会生效。举个例子,下面是创建索引的语句:
CREATE INDEX index1_c ON hao1 (age)

而查询语句是:

select name from hao1 where age = 35;

上例就不会用到索引index1_c。因为name并没有包含在索引中。所以使用全局索引,必须要所有的列都包含在索引中。那么怎样才能使用上索引呢?有三种方法。

1. 创建索引的时候使用覆盖索引。

CREATE INDEX index1_c ON hao1 (age) INCLUDE(name);

这种索引会把name加到索引表里面,同时name也会随着原数据表中的变化而变化。这种方式很明显的缺点是索引表的大小较大,然后就是全局索引不适合写特别多的情况。

2. 使用类似于Oracle的Hint,强制索引。

select /*+ INDEX(HAO1 index1_c)*/ name from hao1 where age = 35;

查询引擎会使用index1_c这个索引,由于它会发现索引表中没有name数据,所以每一行它都会去原数据表中获取name的值。这个强制索引只有在你认为索引有比较好的选择性的时候才是好的选择,也就是说age等于35的行数不多。不然的话,使用Phoenix默认的全表扫描的性能也许会更好。

3. 创建本地索引

CREATE LOCAL INDEX index1_c ON hao1 (age)

本地索引和全局索引不同的是,查询语句中,即使所有的列都不在索引定义中,它也会使用索引,这是本地索引的默认行为。Phoenix知道原数据和索引数据在同一个RegionServer上,能保证索引查找是本地的。

索引的删除

通过如下命令删除一个索引:

drop index index1_c ON hao1;

如果一个被索引的列被删除了,那么这个索引也会被自动删除。如果一个被覆盖索引的列被删除了,那么这个覆盖列也会自动从索引中删除。

时间: 2024-10-14 20:34:05

Phoenix的二级索引(1)的相关文章

HBase集成Phoenix创建二级索引

一.Hbase集成Phoneix 1.下载 在官网http://www.apache.org/dyn/closer.lua/phoenix/中选择提供的镜像站点中下载与安装的HBase版本对应的版本.本地使用的1.2.5,故下载的apache-phoenix-4.11.0-HBase-1.2/的tar.gz包. 2.上传并解压 tar -zxvf apache-phoenix-4.13.1-HBase-1.2-bin.tar.gzmv apache-phoenix-4.13.1-HBase-1.

HBase的二级索引,以及phoenix的安装(需再做一次)

一:HBase的二级索引 1.讲解 uid+ts 11111_20161126111111:查询某一uid的某一个时间段内的数据 查询某一时间段内所有用户的数据:按照时间 索引表 rowkey:ts+uid 20161126111111-111111 info:uid uid+ts 检索流程: 从索引表中根据时间段来查询源表rowkey 根据rowkey来查询源表 二:phoenix的安装 1.上传源文件包 2.解压到modules文件夹下 tar -zxvf phoenix-4.2.2-src

phoenix连接hbase数据库,创建二级索引报错:Error: org.apache.phoenix.exception.PhoenixIOException: Failed after attempts=36, exceptions: Tue Mar 06 10:32:02 CST 2018, null, java.net.SocketTimeoutException: callTimeou

环境描述: 操作系统版本:CentOS release 6.5 (Final) 内核版本:2.6.32-431.el6.x86_64 phoenix版本:phoenix-4.10.0 hbase版本:hbase-1.2.6 表SYNC_BUSINESS_INFO_BYDAY数据库量:990万+ 问题描述: 通过phoenix客户端连接hbase数据库,创建二级索引时,报下面的错误: 0: jdbc:phoenix:host-10-191-5-226> create index SYNC_BUSI

HBase的二级索引

HBase的二级索引,以及phoenix的安装(需再做一次) 一:HBase的二级索引 1.讲解 uid+ts  11111_20161126111111:查询某一uid的某一个时间段内的数据 查询某一时间段内所有用户的数据:按照时间 索引表 rowkey:ts+uid 20161126111111-111111 info:uid uid+ts 检索流程: 从索引表中根据时间段来查询源表rowkey 根据rowkey来查询源表 二:phoenix的安装 1.上传源文件包 2.解压到modules

HBase二级索引的设计

摘要 最近做的一个项目涉及到了多条件的组合查询,数据存储用的是HBase,恰恰HBase对于这种场景的查询特别不给力,一般HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowKey中显然不太可能),或者全表扫描再结合过滤器筛选出目标数据(太低效),所以通过设计HBase的二级索引来解决这个问题 查询需求 多个查询条件构成多维度的组合查询,需要根据不同组合查询出符合查询条件的数据 HBase的局限性 HBase本身只提供基于行键和全表扫描的查询,而行键索引单一,对于多维度的

HBase协处理器同步二级索引到Solr

一. 背景二. 什么是HBase的协处理器三. HBase协处理器同步数据到Solr四. 添加协处理器五. 测试六. 协处理器动态加载 一. 背景 在实际生产中,HBase往往不能满足多维度分析,我们能想到的办法就是通过创建HBase数据的二级索引来快速获取rowkey,从而得到想要的数据.目前比较流行的二级索引解决方案有Lily HBase Indexer,Phoenix自带的二级索引,华为Indexer,以及360的二级索引方案.上面的目前使用比较广泛的应该是Lily HBase Index

HBase二级索引方案总结

转自:http://blog.sina.com.cn/s/blog_4a1f59bf01018apd.html 附hbase如何创建二级索引以及创建二级索引实例:http://www.aboutyun.com/thread-8857-1-1.html 华为二级索引(原理):http://my.oschina.net/u/923508/blog/413129 在HBase中,表格的Rowkey按照字典排序,Region按照RowKey设置split point进行shard,通过这种方式实现的全局

HBase建立二级索引的一些解决方案

HBase的一级索引就是rowkey,我们只能通过rowkey进行检索.如果我们相对hbase里面列族的列列进行一些组合查询,就需要采用HBase的二级索引方案来进行多条件的查询. 常见的二级索引方案有以下几种: 1.MapReduce方案 2.ITHBASE方案 3.IHBASE方案 4.Coprocessor方案 5.Solr+hbase方案 MapReduce方案 IndexBuilder:利用MR的方式构建Index 优点:并发批量构建Index 缺点:不能实时构建Index 举例: 原

基于solr实现hbase的二级索引

一.目的 了解hbase的都知道,由于hbase基于行健有序存储,在查询时使用行健十分高效,然后想要实现关系型数据库那样可以随意组合的多条件查询.查询总记录数.分页等就比较麻烦了.想要实现这样的功能,我们可以采用两种方法: 使用hbase提供的filter, 自己实现二级索引,通过二级索引查询多符合条件的行健,然后再查询hbase. 第一种方法不多说了,使用起来很方便,但是局限性也很大,hbase的filter是直接扫记录的,如果数据范围很大,会导致查询速度很慢.所以如果能先使用行健把记录缩小到