Hive是支持索引的,但基本沒用過,只做了下試驗。
為什么大家都不用,肯定有它的弊端。
Hive索引機制:
在指定列上建立索引,會產生一張索引表(Hive的一張物理表),里面的字段包括,索引列的值、該值對應的HDFS文件路徑、該值在文件中的偏移量;
在執行索引字段查詢時候,首先額外生成一個MR job,根據對索引列的過濾條件,從索引表中過濾出索引列的值對應的hdfs文件路徑及偏移量,輸出到hdfs上的一個文件中,然后根據這些文件中的hdfs路徑和偏移量,篩選原始input文件,生成新的split,作為整個job的split,這樣就達到不用全表掃描的目的。
Hive索引建立過程:
創建索引:
之后在Hive中會創建一張索引表,也是物理表:

Hive index Hive索引
其中,索引表中key字段,就是原表中key字段的值,_bucketname 字段,代表數據文件對應的HDFS文件路徑,_offsets 代表該key值在文件中的偏移量,有可能有多個偏移量,因此,該字段類型為數組。
其實,索引表就相當於一個在原表索引列上的一個匯總表。
生成索引數據
用一個MR任務,以table lxw1234的數據作為input,將索引字段key中的每一個值及其對應的HDFS文件和偏移量輸出到索引表中。
自動使用索引
查詢時候索引如何起效:
- 首先用一個job,從索引表中過濾出key = ‘13400000144_1387531071_460606566970889’的記錄,將其對應的HDFS文件路徑及偏移量輸出到HDFS臨時文件中
- 接下來的job中以臨時文件為input,根據里面的HDFS文件路徑及偏移量,生成新的split,作為查詢job的map任務input
- 不使用索引時候,如下圖所示:
Hive index Hive索引
- table lxw1234的每一個split都會用一個map task去掃描,但其實只有split2中有我們想要的結果數據,map task1和map task3造成了資源浪費。
- 使用索引后,如下圖所示:
Hive index Hive索引
- 查詢提交后,先用一個MR,掃描索引表,從索引表中找出key=’xx’的記錄,獲取到HDFS文件名和偏移量;
- 接下來,直接定位到該文件中的偏移量,用一個map task即可完成查詢,其最終目的就是為了減少查詢時候的input size
手動使用索引
- 其實就是手動完成從索引表中過濾數據的部分,將過濾出來的數據load 到HDFS臨時文件,供查詢任務使用
從以上過程可以看出,Hive索引的使用過程比較繁瑣:
- 每次查詢時候都要先用一個job掃描索引表,如果索引列的值非常稀疏,那么索引表本身也會非常大;
- 索引表不會自動rebuild,如果表有數據新增或刪除,那么必須手動rebuild索引表數據;