Hive命令

基礎命令
show databases; # 查看某個數據庫
use 數據庫;      # 進入某個數據庫
show tables;    # 展示所有表
desc 表名;            # 顯示錶結構
show partitions 表名; # 顯示錶名的分區
show create table_name;   # 顯示創建表的結構

# 建表語句
# 內部表
use xxdb; create table xxx;
# 創建一個表,結構與其他一樣
create table xxx like xxx;
# 外部表
use xxdb; create external table xxx;
# 分區表
use xxdb; create external table xxx (l int) partitoned by (d string)
# 內外部錶轉化
alter table table_name set TBLPROPROTIES ('EXTERNAL'='TRUE'); # 內部錶轉外部表
alter table table_name set TBLPROPROTIES ('EXTERNAL'='FALSE');# 外部錶轉內部表

# 表結構修改
# 重命名錶
use xxxdb; alter table table_name rename to new_table_name;
# 增加字段
alter table table_name add columns (newcol1 int comment ‘新增’);
# 修改字段
alter table table_name change col_name new_col_name new_type;
# 刪除字段(COLUMNS中只放保留的字段)
alter table table_name replace columns (col1 int,col2 string,col3 string);
# 刪除表
use xxxdb; drop table table_name;
# 刪除分區
# 注意:若是外部表,則還需要刪除文件(hadoop fs -rm -r -f  hdfspath)
alter table table_name drop if exists partitions (d='2016-07-01');

# 字段類型
# tinyint, smallint, int, bigint, float, decimal, boolean, string
# 複合數據類型
# struct, array, map
複合數據類型
# array
create table person(name string,work_locations array<string>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
# 數據
biansutao beijing,shanghai,tianjin,hangzhou
linan changchu,chengdu,wuhan
# 入庫數據
LOAD DATA LOCAL INPATH '/home/hadoop/person.txt' OVERWRITE INTO TABLE person;
select * from person;
# biansutao       ["beijing","shanghai","tianjin","hangzhou"]
# linan           ["changchu","chengdu","wuhan"]

# map
create table score(name string, score map<string,int>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';
# 數據
biansutao '數學':80,'語文':89,'英語':95
jobs '語文':60,'數學':80,'英語':99
# 入庫數據
LOAD DATA LOCAL INPATH '/home/hadoop/score.txt' OVERWRITE INTO TABLE score;
select * from score;
# biansutao       {"數學":80,"語文":89,"英語":95}
# jobs            {"語文":60,"數學":80,"英語":99}

# struct
CREATE TABLE test(id int,course struct<course:string,score:int>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
# 數據
1 english,80
2 math,89
3 chinese,95
# 入庫
LOAD DATA LOCAL INPATH '/home/hadoop/test.txt' OVERWRITE INTO TABLE test;
# 查詢
select * from test;
# 1       {"course":"english","score":80}
# 2       {"course":"math","score":89}
# 3       {"course":"chinese","score":95}
配置優化
# 開啓任務並行執行
set hive.exec.parallel=true
# 設置運行內存
set mapreduce.map.memory.mb=1024;
set mapreduce.reduce.memory.mb=1024;
# 指定隊列
set mapreduce.job.queuename=jppkg_high;
# 動態分區,爲了防止一個reduce處理寫入一個分區導致速度嚴重降低,下面需設置爲false
# 默認爲true
set hive.optimize.sort.dynamic.partition=false;
# 設置變量
set hivevar:factor_timedecay=-0.3;
set hivevar:pre_month=${zdt.addDay(-30).format("yyyy-MM-dd")};
set hivevar:pre_date=${zdt.addDay(-1).format("yyyy-MM-dd")};
set hivevar:cur_date=${zdt.format("yyyy-MM-dd")};
# 添加第三方jar包, 添加臨時函數
add jar ***.jar;
# 壓縮輸出,ORC默認自帶壓縮,不需要額外指定,如果使用非ORCFile,則設置如下
hive.exec.compress.output=true
# 如果一個大文件可以拆分,爲防止一個Map讀取過大的數據,拖慢整體流程,需設置
hive.hadoop.suports.splittable.combineinputformat
# 避免因數據傾斜造成的計算效率,默認false
hive.groupby.skewindata
# 避免因join引起的數據傾斜
hive.optimize.skewjoin
# map中會做部分聚集操作,效率高,但需要更多內存
hive.map.aggr   -- 默認打開
hive.groupby.mapaggr.checkinterval  -- 在Map端進行聚合操作的條目數目
# 當多個group by語句有相同的分組列,則會優化爲一個MR任務。默認關閉。
hive.multigroupby.singlemr
# 自動使用索引,默認不開啓,需配合row group index,可以提高計算速度
hive.optimize.index.filter
常用函數
# if 函數,如果滿足條件,則返回A, 否則返回B
if (boolean condition, T A, T B)
# case 條件判斷函數, 當a爲b時則返回c;當a爲d時,返回e;否則返回f
case a when b then c when d then e else f end
# 將字符串類型的數據讀取爲json類型,並得到其中的元素key的值
# 第一個參數填寫json對象變量,第二個參數使用$表示json變量標識,然後用.讀取對象或數組;
get_json_object(string s, '$.key')
# url解析
# parse_url('http://facebook.com/path/p1.php?query=1','HOST')返回'facebook.com' 
# parse_url('http://facebook.com/path/p1.php?query=1','PATH')返回'/path/p1.php' 
# parse_url('http://facebook.com/path/p1.php?query=1','QUERY')返回'query=1',
parse_url()
# explode就是將hive一行中複雜的array或者map結構拆分成多行
explode(colname)
# lateral view 將一行數據adid_list拆分爲多行adid後,使用lateral view使之成爲一個虛表adTable,使得每行的數據adid與之前的pageid一一對應, 因此最後pageAds表結構已發生改變,增加了一列adid
select pageid, adid from pageAds
lateral view explode(adid_list) adTable as adid
# 去除兩邊空格
trim()
# 大小寫轉換
lower(), upper()
# 返回列表中第一個非空元素,如果所有值都爲空,則返回null
coalesce(v1, v2, v3, ...)
# 返回當前時間
from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss')
# 返回第二個參數在待查找字符串中的位置(找不到返回0)
instr(string str, string search_str)
# 字符串連接
concat(string A, string B, string C, ...)
# 自定義分隔符sep的字符串連接
concat_ws(string sep, string A, string B, string C, ...)
# 返回字符串長度
length()
# 反轉字符串
reverse()
# 字符串截取
substring(string A, int start, int len)
# 將字符串A中的符合java正則表達式pat的部分替換爲C;
regexp_replace(string A, string pat, string C)
# 將字符串subject按照pattern正則表達式的規則進行拆分,返回index制定的字符
# 0:顯示與之匹配的整個字符串, 1:顯示第一個括號裏的, 2:顯示第二個括號裏的
regexp_extract(string subject, string pattern, int index)
# 按照pat字符串分割str,返回分割後的字符串數組
split(string str, string pat)
# 類型轉換
cast(expr as type)
# 將字符串轉爲map, item_pat指定item之間的間隔符號,dict_pat指定鍵與值之間的間隔
str_to_map(string A, string item_pat, string dict_pat)
# 提取出map的key, 返回key的array
map_keys(map m)
# 日期函數
# 日期比較函數,返回相差天數,datediff('${cur_date},d)
    datediff(date1, date2)
HQL和SQL的差異點
# 1 select distinct 後必須指定字段名
# 2 join 條件僅支持等值關聯且不支持or條件
# 3 子查詢不能在select中使用;
# 4 HQL中沒有UNION,可使用distinct+ union all 實現 UNION;
# 5 HQL以分號分隔,必須在每個語句結尾寫上分號;
# 6 HQL中字符串的比較比較嚴格,區分大小寫及空格,因此在比較時建議upper(trim(a))=upper(trim(b))
# 7 日期判斷,建議使用to_date(),如:to_date(orderdate)=‘2016-07-18’
# 8 關鍵字必須在字段名上加``符號,如select `exchange` from xxdb.xxtb;
# 9 數據庫和表/視圖之間僅有1個點,如xx_db.xx_tb;

# HQL不支持update/delete
# 實際採用union all + left join (is null)變相實現update
# 思路:
# 1 取出增量數據;
# 2 使用昨日分區的全量數據通過主鍵左連接增量數據,並且只取增量表中主鍵爲空的數據(即,取未發生變化的全量數據);
# 3 合併1、2的數據覆蓋至最新的分區,即實現了update;

# HQL delete實現
# 採用not exists/left join(is null)的方法變相實現。
# 1.取出已刪除的主鍵數據(表B);
# 2.使用上一個分區的全量數據(表A)通過主鍵左連接A,並且只取A中主鍵爲空的數據,然後直接insert overwrite至新的分區;
基本概念
# hive
hive是基於hadoop的一個數據倉庫工具,可以將結構化的數據文件映射爲一張數據庫庫表,並提供類SQL查詢功能。
# 基本組成
用戶接口:CLI,shell命令行;JDBC/ODBC是hive的java實現;webGUI是通過瀏覽器訪問hive;
元數據存儲:通常是存儲在關係數據庫如mysql, derby中;hive的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否爲外部表),表的數據所在目錄等。
解釋器,編譯器,優化器完成HQL查詢語句從詞法分析,語法分析,編譯,優化以及查詢計劃的生成。生成的查詢存儲在HDFS中,並隨後有mapreduce調用執行。
因此,hive與Hadoop的關係可以理解爲用戶發出SQL查詢語句,hive將查詢存儲在HDFS中,然後由mapreduce調用執行。
# table
Hive 中的 Table 和數據庫中的 Table 在概念上是類似的,每一個 Table 在 Hive 中都有一個相應的目錄存儲數據。例如,一個表 pvs,它在 HDFS 中的路徑爲:/wh/pvs,其中,wh 是在 hive-site.xml 中由 ${hive.metastore.warehouse.dir} 指定的數據倉庫的目錄,所有的 Table 數據(不包括 External Table)都保存在這個目錄中。
# partition
Partition 對應於數據庫中的 Partition 列的密集索引,但是 Hive 中 Partition 的組織方式和數據庫中的很不相同。在 Hive 中,表中的一個 Partition 對應於表下的一個目錄,所有的 Partition 的數據都存儲在對應的目錄中。例如:pvs 表中包含 ds 和 city 兩個 Partition,則對應於 ds = 20090801, ctry = US 的 HDFS 子目錄爲:/wh/pvs/ds=20090801/ctry=US;對應於 ds = 20090801, ctry = CA 的 HDFS 子目錄爲;/wh/pvs/ds=20090801/ctry=CA
# buckets
Buckets 對指定列計算 hash,根據 hash 值切分數據,目的是爲了並行,每一個 Bucket 對應一個文件。將 user 列分散至 32 個 bucket,首先對 user 列的值計算 hash,對應 hash 值爲 0 的 HDFS 目錄爲:/wh/pvs/ds=20090801/ctry=US/part-00000;hash 值爲 20 的 HDFS 目錄爲:/wh/pvs/ds=20090801/ctry=US/part-00020
# external table
External Table 指向已經在 HDFS 中存在的數據,可以創建 Partition。它和 Table 在元數據的組織上是相同的,而實際數據的存儲則有較大的差異。
Table 的創建過程和數據加載過程(這兩個過程可以在同一個語句中完成),在加載數據的過程中,實際數據會被移動到數據倉庫目錄中;之後對數據對訪問將會直接在數據倉庫目錄中完成。刪除表時,表中的數據和元數據將會被同時刪除。
External Table 只有一個過程,加載數據和創建表同時完成(CREATE EXTERNAL TABLE ……LOCATION),實際數據是存儲在 LOCATION 後面指定的 HDFS 路徑中,並不會移動到數據倉庫目錄中。當刪除一個 External Table 時,僅刪除元數據,表中的數據不會真正被刪除。
# 全量數據和增量數據
查看分區信息
如果分區的大小隨時間增加而增加,則最新的分區爲全量數據
如果分區的大小隨時間增加而大小上下變化,則每個分區都是增量數據
實際使用
# 增加分區
insert overwrite table table_name partition (d='${pre_date}')

# 建表語句
# 進行分區,每個分區相當於是一個文件夾,如果是雙分區,則第二個分區作爲第一個分區的子文件夾
drop table if exists employees;  
create table  if not exists employees(  
       name string,  
       salary float,  
       subordinate array<string>,  
       deductions map<string,float>,  
       address struct<street:string,city:string,num:int>  
) partitioned by (date_time string, type string)
row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':'
lines terminated by '\n'
stored as textfile
location '/hive/...';

# hive桶
# 分區是粗粒度的,桶是細粒度的
# hive針對某一列進行分桶,對列值哈希,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶中
create table bucketed_user(id int, name string)
clustered by (id) sorted by (name) into 4 buckets
row format delimited
fields terminated by '\t'
stored as textfile;
# 注意,使用桶表的時候我們要開啓桶表
set hive.enforce.bucketing=true;
# 將employee表中的name和salary查詢出來插入到表中
insert overwrite table bucketed_user select salary, name from employees

如果字段類型是string,則通過get_json_object提取數據;
如果字段類型是struct或map,則通過col['xx']方式提取數據;

shell指令
#!/bin/bash
hive -e "use xxxdb;"

cnt = `hive -e "..."`
echo "cnt=${cnt}"

# 循環語句
for ((i=1; i<=10; i+=1))
do
pre_date=`date -d -${i}days +%F`
done

# 定義日期
pre_date=`date -d -1days +%F`
pre_week=`date -d -7days +%F`

# 設置環境變量
export JAVA_HOME=jdk;
References:

複合數據結構map, struct, array用法,非常用函數介紹:https://my.oschina.net/leejun2005/blog/120463

regexp_extract: https://www.cnblogs.com/skyEva/p/5175377.html

lateral view和explode: https://blog.csdn.net/bitcarmanlee/article/details/51926530

基本概念:分區,桶…:https://blog.csdn.net/gamer_gyt/article/details/47210331

hive基本概念:https://blog.csdn.net/tototuzuoquan/article/details/73003730

 

發佈了98 篇原創文章 · 獲贊 165 · 訪問量 163萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章