1. 程式人生 > >Hive HiveQL基礎知識及常用語句總結

Hive HiveQL基礎知識及常用語句總結

基礎語句

CREATE DROP 建表、刪表

  • 建表
--------------------------------------
-- 1. 直接建表
--------------------------------------

-- 建立非分割槽表時,省去後半部分即可
create table if not exists table_name(
id string comment 'id ',
num string comment '數值'  
)
partitioned by (
ym string comment  '月份 ' 
);

--------------------------------------
-- 2. 複製其他表的表結構 -------------------------------------- create table if not exists new_table like old_table; -------------------------------------- -- 3. 從其他表選取資料建立並插入新表 -------------------------------------- create table if not exists new_table as select * from old_table;
  • 刪表
drop table table_name ;

ALTER 更改表結構

分割槽

  • 新增分割槽
alter table table_name 
add if not exists partition (y='2016',m='12');
  • 刪除分割槽
ALTER TABLE table_name DROP IF EXISTS PARTITION (ym='201706');
  • 重新命名分割槽
 ALTER TABLE table_name PARTITION (y='2017',m='05') 
 RENAME TO PARTITION (y='2017',m='06'); 

  • 刪除列
ALTER
TABLE table_name DROP COLUMN id;
  • 增加列
Alter table table_name add COLUMNS (id string comment '代號');
  • 修改列 (此處可用於 修改欄位註釋)
ALTER TABLE table_name CHANGE id level string comment '層級代號';
  • 替換列
ALTET TABLE table_name REPLACE COLUMNS
(id_new string COMMENT '新欄位1', level_new string COMMENT '新欄位2');

  • 重命名錶名
ALTER TABLE old_table RENAME TO new_table;

INSERT 插入

  • 插入單條資料 (Hive 已支援單條插入)
 insert into table_name  values(201705,'lol');
  • 插入分割槽表
 insert overwrite table  table_name   PARTITION (y='2017',m='01')
 select * 
 from table_name_2 
  where pt = concat('2017','01'); 

LOAD 載入

  • 重寫載入分割槽表 (非分割槽表同理)
LOAD DATA LOCAL INPATH 'total.txt' overwrite into table table_name partition (y='2016',m='12');

其他語句

  • 其他基礎SQL類似的語句不再贅述,此處再多列舉幾個常用語句:
-- 列舉庫或表
SHOW DATABASES/TABLES;
-- 根據關鍵字查詢庫或表
SHOW DATABASES/TABLES LIKE "*keyword*";
-- 列舉所有函式
SHOW FUNCTIONS;
-- 檢視分割槽
SHOW PARTITIONS test_table;
-- 檢視建表語句
SHOW CREATE TABLE table_name;
-- 詳細描述,包括建表時間、最後更新時間、行數統計等。
DESC FORMATTED test_table;
-- 解釋語句
EXPLAIN select * from dual;
-- 清空表
truncate table table_name;

函式、技巧、方法

  • 執行順序理解
    根據 explain 語句的使用發現,在執行以下語句時:
    TableScan步驟,where條件中若有分割槽篩選條件且目標分割槽確實存在、且判斷方式為=時,自動進行過濾, 然後再在Filter Operator進行其他條件的篩選:
    predicate: (latitude is not null and (UDFToDouble(longitude) > 100.0) AND (UDFToDouble(ym) > 201701.0)) (type: boolean)
    predicate: (lat_avg is not null and lng_avg is not null) (type: boolean)
    所以, 先join在where和先where在join是等等價的
  select b.*, a.name,a.price,a.city  
  from table_name_a a 
  join table_name_b b
  on round(b.lng_avg,2) = round(a.longitude,2) 
  and round(b.lat_avg,2) = round(a.latitude,2) 
  where  a.longitude  >100  
  • shell內通過hive -v " "呼叫執行HiveQL語句時,如需要註釋,請注意轉義問題

    1. 註釋的那條語句不能含有分號;
    2. 註釋語句後接語句儘量避免導jar包的語句
    3. 避免使用 /* */
  • 選擇除某幾個欄位外的所有欄位
    當某個表的欄位特別多,若想選取除某幾個欄位外的所有欄位時,這時語句寫起來就會很麻煩,比如有時兩個表join的條件的欄位名相同時,只能保留一個欄位。但有一個方法可以解決這個問題,如下:

set hive.support.quoted.identifiers=none;
select `(y|m|d)?+.+` from dual;
需注意:
括號內不能有空格
在shell裡呼叫時需要對這個反引號進行轉義
  • 通過concat_wscollect_setstr_to_map的使用,實現字串轉map
str_to_map(concat_ws(',',collect_set(concat_ws(':',key, cast(value as string)))))
  • avg()函式會自動剔除NULL,總數除以非NULL個數
  • 字串擷取函式substrsubstring是等價的
    substr(string A, int start, int len)
    substring(string A, int start, int len)
  • x between a and b 等同於 a<= x <=b

  • 子查詢加最好要加別稱
    報錯:Failed rule: ‘identifier’ in subquery source
    解決:子查詢加 別稱

  • 設定佇列問題, mapred.job.queue.namemapreduce.job.queuename

set mapred.job.queue.name=queue_xx;

MRv2重新命名了MRv1中的所有配置引數,但相容MRv1中的舊引數,只不過會列印一條警告日誌提示使用者引數過期。詳見此篇博文

  • 查詢表的實際更新情況
    desc formatted 的結果往往只有CreateTimeLastAccessTime經常為UNKNOWN的狀態,可以用hadoop 指令去查詢資料檔案的真實更新時間:hadoop fs ‐ls truePath/databaseName.db/tableName/

調優

佔個坑,有時間再來填

Hive裡的坑點

  • limit m,n 的問題
    使用語句:create table a as select * from b limit m,n時,會導致新建表a內無資料,解決辦法:
    1. 看似可以其實並不好使: create table a as select * from (select * from b limit m,n ) t
    2. 解決: 使用row_number() 加序號,根據序號選取
  • NULL 值問題
    1. length(NULL) 等於NULL
    2. NULL空字串:
      由下可見:NULL不可以與字串或數值比較,''可與字串比較但不可與數值比較
hive (xx_safe)> select * from dual;
OK
dual.lol
100
50
1
1
2
fangjiale
NULL
   --(此處為'')
hive (xx_safe)> select * from dual where lol !='1';
OK
dual.lol
fangjiale
100
50
2
   --(此處為'')  
hive (xx_safe)> select * from dual where lol !=1;
OK
dual.lol
100
50
2