一起聊一聊hive的索引优化原创
大家好,我是球球,今天给大家聊聊hive的索引。
索引的作用
Hive从0.7.0版本开始加入了索引,目的是提高Hive表指定列的查询速度。没有索引的时候,Hive在执行查询时需要加载整个表或者整个分区,然后处理所有的数据,但当在指定列上存在索引,再通过指定列查询时,那么只会加载和处理部分文件。此外,同传统关系型数据库一样,增加索引在提升查询速度的同时,会额外消耗资源去创建索引和需要更多的磁盘空间存储索引。Hive支持索引,但是Hive的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键。
Hive索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少MapReduce任务中需要读取的数据块的数量。
在可以预见到分区数据非常庞大的情况下,索引常常是优于分区的。
虽然Hive并不像事物数据库那样针对个别的行来执行查询、更新、删除等操作。它更多的用在多任务节点的场景下,快速地全表扫描大规模数据。但是在某些场景下,建立索引还是可以提高Hive表指定列的查询速度。(虽然这个效果还不是很好)
索引适用的场景
适用于不更新的静态字段。以免总是重建索引数据。每次建立、更新数据后,都要重建索引以构建索引表。
Hive索引的机制如下:
hive在指定列上建立索引,会产生一张索引表(Hive的一张物理表),里面的字段包括,索引列的值、该值对应的HDFS文件路径、该值在文件中的偏移量;
v0.8后引入bitmap索引处理器,这个处理器适用于排重后,值较少的列(例如,某字段的取值只可能是几个枚举值)
因为索引是用空间换时间,索引列的取值过多会导致建立bitmap索引表过大。
但是,很少遇到hive用索引的,说明还是有缺陷or不合适的地方的,3.0 后hive去掉了索引.
hive索引的机制和原理
Hive的索引其实是一张索引表(Hive的物理表),在表里面存储索引列的值,该值对应的HDFS的文件路径,该值在数据文件中的偏移量。当Hive通过索引列执行查询时,首先通过一个MR Job去查询索引表,根据索引列的过滤条件,查询出该索引列值对应的HDFS文件目录及偏移量,并且把这些数据输出到HDFS的一个文件中,然后再根据这个文件中去筛选原文件,作为查询Job的输入。
优缺点
-
优点:
-
可以避免全表扫描和资源浪费 -
可以加快含有group by的语句的查询速度 -
缺点:
-
Hive索引的使用过程比较繁琐:
-
每次查询时候都要先用一个job扫描索引表,如果索引列的值非常稀疏,那么索引表本身也会非常大;
-
索引表不会自动rebuild,如果表有数据新增或删除,那么必须手动rebuild索引表数据;
索引应用
-
创建索引
create index index_name
on table base_table_name (col_name, ...)
as 'index.handler.class.name'
[with deferred rebuild]
[idxproperties (property_name=property_value, ...)]
[in table index_table_name]
[partitioned by (col_name, ...)]
[
[ row format ...] stored as ... | stored by ...
]
[location hdfs_path]
[tblproperties (...)]
[comment "index comment"]
as ‘index.handler.class.name’
指定索引处理器,这里的一般使用org.apache.hadoop.hive.ql.index.compact.compactindexhandler
这个处理器。
[with deferred rebuild]
表明创建一个空索引,也就是说现在还不创建索引
[in table index_table_name]
索引存储在哪个表中。
[idxproperties (property_name=property_value, …)]
索引的参数。一般使用idxproperties (‘creator’ = ‘me’,‘created_at’ = ‘some_time’)
,代表创建者和创建时间。
[partitioned by (col_name, …)]
[
[ row format …] stored as …
| stored by …
]
表明只对某个分区创建索引,若没有该选项则表示对所有分区都创建索引,另外要注意的是index的分区索引默认是和表的分区一致的,也不能对视图view创建索引。
例如:
create index test_index on table test(id)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild
in table test;
-
生成索引数据
刚创建完的Hive索引表是没有数据的,需要生成索引数据
alter index test_index on test rebuild;
-
显示索引
show index on t_travel_members_m;
-
重建数据
建立完索引之后 需要重建索引数据,会触发一个mr job
alter index index_bill_id on t_travel_members_m rebuild;
-
使用索引
SET hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
SET hive.optimize.index.filter=true;
SET hive.optimize.index.filter.compact.minsize=0;
-
删除索引
drop index test_index on test;
总结
我们可以发现Hive的索引功能现在还相对较晚,提供的选项还较少。但是,索引被设计为可使用内置的可插拔的java代码来定制,用户可以扩展这个功能来满足自己的需求。当然不是说所有的查询都会受惠于Hive索引。用户可以使用EXPLAIN语法来分析HiveQL语句是否可以使用索引来提升用户查询的性能。像RDBMS中的索引一样,需要评估索引创建的是否合理,毕竟,索引需要更多的磁盘空间,并且创建维护索引也会有一定的代价。用户必须要权衡从索引得到的好处和代价。