一篇文章徹底掌握 Hive 中的 Order/Sort/Cluster/Distribute by和 Bucket 桶表
作者: IT明哥
本篇文章,我們來總結下,HIVE 中的 order/sort/cluster/distribute by 和 BUCKET 桶表。
大家好,我是明哥!
本片文章,我們來總結下,HIVE 中的 order/sort/cluster/distribute by 和 BUCKET 桶表
1 ORDER BY
- ORDER BY 會對 SQL 的最終輸出結果數據做全局排序;
- ORDER BY 底層只會有一個Reducer 任務 (多個Reducer無法保證全局有序);
- 當然只有一個 Reducer 任務時,如果輸入數據規模較大,會消耗較長的計算時間;
- ORDER BY 默認的排序順序是遞增 ascending (ASC).
- 示例語句:select distinct cust_id,id_no,part_date from ads_api_cda_basic_info_parquet_pt order by cust_id;
2 SORT BY
- SORT BY 不是對 SQL 的最終輸出結果數據做排序,而是對 MAP 端的輸出數據,在進入 reducer 前,根據指定的字段進行排序;
- SORT BY 不會影響 REDUCER 的個數;
- SORT BY 只會保證每個 reducer 內部的數據的順序性,而不會保證 SQL 最終輸出結果的全局有序性;
- 示例語句:select distinct cust_id,id_no,part_date from ads_api_cda_basic_info_parquet_pt SORT by cust_id;圖片
3 DISTRIBUTE BY
- DISTRIBUTE BY 指定了將 MAP 端的輸出記錄交給哪個 reducer 進一步處理的分發規則;
- DISTRIBUTE BY 不會影響 REDUCER 的個數;
- 具有相同的 Distribute By 字段的MAP端的輸出數據,會被分發給同一個 reducer 進行處理 (默認是采用hash取模算法);
- Distribute By 并不會保證每個 REDUCER 內部的所有記錄的順序性;
- 示例語句:select distinct cust_id,id_no,part_date from ads_api_cda_basic_info_parquet_pt distribute by cust_id;圖片
- DISTRIBUTE BY 和 SORT BY 配合使用,可以保證每個 REDUCER 內部的所有記錄的順序性(此時,Distribute By 分區字段 和 SORT BY 排序字段,可以是不同的字段);
- 示例語句:select distinct cust_id,id_no,part_date from ads_api_cda_basic_info_parquet_pt distribute by cust_id sort by id_no;
- DISTRIBUTE BY 和 SORT BY 配合使用,并選用合適的 DISTRIBUTE BY 字段,可以解決以下問題:
- Map輸出的文件大小不均;
- Reduce輸出文件大小不均;
- 小文件過多;
- 文件超大;
4 CLUSTER BY
- CLUSTER BY 等價于配合使用 DISTRIBUTE BY 和 SORT BY;
- CLUSTER BY底層的 Distribute By 分區字段 和 SORT BY 排序字段,是同一個字段;
- CLUSTER BY 不會影響 REDUCER 的個數;
- 示例語句:select distinct cust_id,id_no,part_date from ads_api_cda_basic_info_parquet_pt cluster by cust_id;
CLUSTER BY in spark web ui
5 BUCKET 桶表
HIVE中有 BUCKET 桶表,桶表具有以下優勢:
- 桶表可以支持高效的 sampling 取樣;
- 桶表對高效的 mapside joins 的支持更好;
- 聲明桶表時,需要指定分桶字段和桶的個數(CLUSTERED BY(user_id) INTO 31 BUCKETS);
- 桶表的寫入操作,在底層執行時,會自動添加 CLUSTER BY 子語句 以按桶表聲明時指定的分桶字段來分布數據;(如果是 0.x 或 1.x 的 HIVE 版本,需要配置參數 set hive.enforce.bucketing = true; HIVE 2.X 后,該參數被remove了,等價于總是TURE;)
- 桶表的寫入操作,在底層執行時,會有reducer,且reducer的個數,會自動使用聲明桶表時指定的桶的個數;(如果是 0.x 或 1.x 的 HIVE 版本,需要配置參數 set hive.enforce.bucketing = true; HIVE 2.X 后,該參數被remove了,等價于總是TURE;)
- 通過選用合適的分桶字段和分桶數,桶表可以有效管控表底層的小文件的個數,進而緩解數據傾斜問題和小文件問題;
- 使用桶表來緩解數據傾斜問題和小文件問題時,所有的更改都在 DDL 這一層,不需要更改 DML 語句添加 CLUSTER/DISTRIBUTE BY 子語句,同時由于 DDL 是系統上線時或后續運維優化調整時的一次性的操作,增加了系統的彈性和運維優化的便利性;
- 可以使用類似以下 DDL 語句來聲明 BUCKET 桶表,類似以下DML語句來操作桶表:
- ## DDL
- CREATE TABLE bucket_tableA(user_id BIGINT, firstname STRING, lastname STRING)
- COMMENT 'A bucketed copy of user_info'
- PARTITIONED BY(ds STRING)
- CLUSTERED BY(user_id) INTO 31 BUCKETS;
- ## DML
- INSERT OVERWRITE bucket_tableA select * from xx;
INSERT OVERWRITE bucket_tableA SPARK WEB UI
責任編輯:武曉燕
來源:
明哥的IT隨筆