一起聊一聊hive的索引最佳化。

帶你聊技術發表於2023-01-03


大家好,我是球球,今天給大家聊聊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中的索引一樣,需要評估索引建立的是否合理,畢竟,索引需要更多的磁碟空間,並且建立維護索引也會有一定的代價。使用者必須要權衡從索引得到的好處和代價。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2930581/,如需轉載,請註明出處,否則將追究法律責任。

相關文章