Hive SQL優化方式及使用技巧


HIVE簡介

Hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射為一張數據庫表,並提供簡單的sql查詢,可以將sql語句轉換為MapReduce任務進行運行

同時,hive也允許熟悉map-reduce的開發者開發自定義的mapper和reducer來處理內建的mapper和reducer無法處理的復雜的分析工作。

用戶發出sql命令----> hive處理並轉換為MapReduce---->提交任務到hadoop並運行在hdfs

HIVE DDL

Hive建表(壓縮表和非壓縮表)

一個表可以擁有一個或者多個分區,每個分區以文件夾的形式單獨存在於表文件夾的目錄下

創建表:指定exterbal關鍵字的就是外部表,沒有就是內部表。內部表在drop的時候會從hdfs上刪除數據,外部表不會刪除

如果不指定數據庫,hive會把表創建在默認數據庫下。

創建內部表:

create table if not exists `my_inner_table`(
`id` bigint comment '邏輯id,記錄的唯一id',
`user_id` string comment 'user_id'
) comment '內部表'
partitioned by (`dt` string comment 'date, yyyy-MM-dd')
ROW FORMAT DELIMITED
    FIELDS TERMINATED BY '\001'
    lines terminated by '\n'
STORED AS TEXTFILE

創建外部表:

create external table if not exists `my_external_table`(
`id` bigint comment '邏輯id,記錄的唯一id',
`user_id` string comment 'user_id'
) comment '外部表'
partitioned by (`dt` string comment 'date, yyyy-MM-dd')
ROW FORMAT DELIMITED
    FIELDS TERMINATED BY '\001'
    lines terminated by '\n'
STORED AS TEXTFILE
location 'hdfs://user/user.sql/';

HIVE SQL優化

優化的根本思想:

  • 盡早盡量過濾數據,減少每個階段的數據量
  • 減少job數
  • 解決數據傾斜問題

盡早盡量過濾數據,減少每個階段的數據量

1.列裁剪:

例如某表有a,b,c,d,e五個字段,但是我們只需要a和b,那么請用select a,b from table 而不是select * from table

2.分區裁剪:

在查詢的過程中減少不必要的分區,即盡量指定分區

3.利用hive的優化機制減少job數:

不論是外關聯outer join還是內關聯inner join,如果join的key相同,不管有多少表,都會合並為一個MapReduce任務:

select a.val,b.val,c.val from a JOIN b ON (a.key = b.key1) JOIN c ON (c.key2 = b.key1)    ----一個job

select a.val,b.val,c.val from a JOIN b ON (a.key = b.key1) JOIN c ON (c.key2 = b.key2)    ----兩個job

4.善用multi-insert:

#查詢了兩次a
insert overwrite table tmp1
select ... from a where 條件1;
insert overwrite table tmp2
select ... from a where 條件2;

#查詢了一次a
from a
insert overwrite table tmp1
select ... where 條件1
insert overwrite table tmp2
select ... where 條件2

5.善用union all:

不同表的union all相當於multi inputs,同一表的union all相當於map一次輸出多條

6.避免笛卡爾積:關聯的時候一定要寫關聯條件

7.join前過濾掉不需要的數據

#hive0.12之前,會先把a全部數據和b的全部數據進行了關聯,然后再篩選條件,0.12之后做了優化
1. select a.val,b.val from a LEFT OUTER JOIN b ON (a.key=b.key)where a.dt='2020-05-07' and b.dt='2020-05-07'

#優化后的方案
2.select x.val,y.val from 
(select key, val from a where a.dt='2020-05-07') x
LEFT OUTER JOIN
(select key, val from b where b.dt='2020-05-07') y
ON x.key=y.key

8.小表放前大表放后

在編寫帶有join的代碼語句時,應該將條目少的表/子查詢放在join操作符的前面

因為在Reduce階段,位於join操作符左邊的表會先被加載到內存,載入條目較少的表可以有效的防止內存溢出(OOM)。所以對於同一個key來說,對應的value值小的放前面,大的放后面

9.在map階段進行join

join階段有兩種,一種是在map階段進行的,一種是在reduce階段進行的。當小表和大表進行join時,盡量采用mapjoin,即在map端完成,盡早結合數據,使reduce端接收數據量減少。同時可以避免小表與大表join產生的數據傾斜。

如果一個表特別小,推薦用mapjoin;如果不是,我們一般用reduce join

MAPJOIN寫法:

select /*+ MAPJOIN(b) */ a.value,b.value from a join b on a.key=b.key

10.hive0.13之前實現IN和EXISTS

LEFT SEMI JOIN是IN和EXISTS的一種高效實現,在hive0.13之前是不支持IN和EXISTS的

1.select a.key,a.value from a where a.key in (select b.key from b)(hive0.13前不支持)

2.select a.key,a.value from a left outer join b on a.key=b.key where b.key is not null

3.select a.key,a.value from a left semi join b on a.key=b.key

4.select a.key,a.value from a JOIN b ON (a.key=b.key) 

 LEFT SEMI JOIN產生的數據不會重復。

11.使用動態分區

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

create table my_table(
id bigint
) partitioned by(dt string)
STORED AS TEXTFILE;

insert overwrite table my_table partition(dt)
select id,dt from tmp_table

12.union all優化

hive0.13之前不支持union all直接放外層,必須外層套一個查詢,例如:

select key,value from a
union all
select key,value from b

是不支持的。

hive對union all的優化只局限於非嵌套查詢。

select * from(
select key,value from a group by key,value
union all
select key,value from b group by key,value
)
---- 三個job

select key,value from(
select key,value from a union all
select key,value from b
) as tmp
group by tmp.key,tmp.value
---- 一個job,用於小表

不同表太多的union all,不推薦使用。可以寫在中間表的不同分區里,然后再進行union all

13.盡量避免使用distinct

盡量避免使用distinct進行重排,特別是大表,容易產生數據傾斜(key一樣在一個reduce處理)。使用group by替代

select distinct key from a

select key from a group by key

14.排序優化

只有order by產生的結果是全局有序的,可以根據實際場景進行選擇排序

  • order by實現全局排序,一個reduce實現,由於不能並發執行,所以效率低
  • sort by實現部分有序,單個reduce的輸出結果是有序的,效率高,通常與distribute by一起使用(distribute by 關鍵詞可以指定map到reduce的key分發)
  • cluster by col1等價於distribute by col1 sort by col1,但不能指定排序規則

15.使用explain dependency查看sql實際掃描多少分區

 

 

轉載請注明出處:https://www.cnblogs.com/fnlingnzb-learner/p/13087976.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM