1. 程式人生 > >hive中 常用操作

hive中 常用操作

本篇文章主要介紹一下hive的常用sql 操作

  1. 新增分割槽
    一次新增一個分割槽
    ALTER TABLE table_name ADD PARTITION (partCol = 'value1') location 'loc1'; //示例
    ALTER TABLE table_name ADD IF NOT EXISTS PARTITION (dt='20130101') LOCATION '/user/hadoop/warehouse/table_name/dt=20130101'; //一次新增一個分割槽

一次新增多個分割槽

ALTER TABLE $abc$ ADD IF NOT EXISTS PARTITION(p_provincecode=$abc.p_provincecode$,p_year=$abc.p_year$,p_month=$abc.p_month$) LOCATION '/hadoop路徑/p_provincecode=$abc.p_provincecode$/p_year=$abc.p_year$/p_month=$abc.p_month$/'
ALTER TABLE page_view ADD PARTITION (dt='2008-08-08', country='us') location '/path/to/us/part080808' PARTITION (dt='2008-08-09', country='us') location '/path/to/us/part080809';  //
  1. 刪除分割槽
ALTER TABLE login DROP IF EXISTS PARTITION (dt='2008-08-08');
ALTER TABLE page_view DROP IF EXISTS PARTITION (dt='2008-08-08', country='us');
  1. 修改分割槽
ALTER TABLE table_name PARTITION (dt='2008-08-08') SET LOCATION "new location";
ALTER TABLE table_name PARTITION (dt='2008-08-08') RENAME TO PARTITION (dt='20080808');
  1. 新增列(欄位)
ALTER TABLE table_name ADD COLUMNS (col_name STRING);  //在所有存在的列後面,但是在分割槽列之前新增一列
  1. 修改列
CREATE TABLE test_change (a int, b int, c int);
/* will change column a's name to a1*/
ALTER TABLE test_change CHANGE a a1 INT;
  1. hive刪除欄位
ALTER TABLE wireless_union_data_export_part1 REPLACE COLUMNS();

7.修改表屬性

alter table table_name set TBLPROPERTIES ('EXTERNAL'='TRUE');  //內部錶轉外部表 
alter table table_name set TBLPROPERTIES ('EXTERNAL'='FALSE');  //外部錶轉內部表

8.表的重新命名

ALTER TABLE table_name RENAME TO new_table_name

gbase修改欄位只能先刪掉欄位,然後再新增
gbase刪除欄位
alter table table_name drop 欄位名

gbase新增欄位
alter table table_name add COLUMN col_name STRING;

gbase清除表資料不刪除表
delete 表名
drop 表名
  1. 匯入資料
load data local inpath '/home/hadoop/ip.txt' [OVERWRITE] into table tab_ext;
  1. external表
    EXTERNAL關鍵字可以讓使用者建立一個外部表,在建表的同時指定一個指向實際資料的路徑(LOCATION),Hive 建立內部表時,會將資料移動到資料倉庫指向的路徑;若建立外部表,僅記錄資料所在的路徑,不對資料的位置做任何改變。
    為了避免原始檔丟失的問題,可以建立external表,資料來源可以在任意位置。
CREATE EXTERNAL TABLE tab_ip_ext(id int, name string,
     ip STRING,
     country STRING)
 ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
 STORED AS TEXTFILE
 LOCATION '/external/hive';

在建立表的時候,就指定了HDFS檔案路徑,因此,原始檔上傳到/external/hive/資料夾即可。

外部表刪除時,只刪除元資料資訊,儲存在HDFS中的資料沒有被刪除。

  1. 分桶表
    Hive裡的分桶=MapReduce中的分割槽,而Hive中的分割槽只是將資料分到了不同的資料夾。
create table stu_buck(Sno int,Sname string,Sex string,Sage int,Sdept string)
clustered by(Sno) 
sorted by(Sno DESC)
into 4 buckets
row format delimited
fields terminated by ',';

一般不適用load資料進入分桶表,因為load進入的資料不會自動按照分桶規則分為四個小檔案。所以,一般使用select查詢向分桶表插入檔案。
設定變數,設定分桶為true, 設定reduce數量是分桶的數量個數

set hive.enforce.bucketing = true;
set mapreduce.job.reduces=4;

insert overwrite table student_buck
select * from student cluster by(Sno);

insert overwrite table stu_buck
select * from student distribute by(Sno) sort by(Sno asc);

其中,可以用distribute by(sno) sort by(sno asc)替代cluster by(Sno),這是等價的。cluster by(Sno) = 分桶+排序
先分發,再區域性排序。區別是distribute更加靈活,可以根據一個欄位分割槽,另外欄位排序。
第二個子查詢的輸出了4個檔案作為主查詢的輸入。

分桶表的原理與作用
原理:
Hive是針對某一列進行桶的組織。Hive採用對列值雜湊,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶當中。(原理和MapReduce的getPartition方法相同)

作用:
(1) 最大的作用是用來提高join操作的效率;
前提是兩個都是分桶表且分桶數量相同或者倍數關係?

思考這個問題:
select a.id,a.name,b.addr from a join b on a.id = b.id;
如果a表和b表已經是分桶表,而且分桶的欄位是id欄位
做這個join操作時,還需要全表做笛卡爾積嗎?
對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那麼將儲存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的資料量。

(2)取樣(sampling)更高效。在處理大規模資料集時,在開發和修改查詢的階段,如果能在資料集的一小部分資料上試執行查詢,會帶來很多方便。

  1. insert語句
Hive一條一條的insert太慢。
但是可以批量的insert.實際就是想資料夾中追加檔案。
  1. 儲存select查詢結果的幾種方式
1、將查詢結果儲存到一張新的hive表中
create table t_tmp
as
select * from t_p;

2、將查詢結果儲存到一張已經存在的hive表中
insert into table t_tmp
select * from t_p;

3、將查詢結果儲存到指定的檔案目錄(可以是本地,也可以是HDFS)
insert overwrite local directory '/home/hadoop/test'
select * from t_p;

插入HDFS
insert overwrite directory '/aaa/test'
select * from t_p;

14.檢視、刪除

SELECT [ALL | DISTINCT] select_expr, select_expr, ... 
FROM table_reference
[WHERE where_condition] 
[GROUP BY col_list [HAVING condition]] 
[CLUSTER BY col_list 
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] 
] 
[LIMIT number]

常用函式

1.isnull(string a) --如果a是null,返回flase,如果啊不為空,返回true
2.ROUND(double a)四捨五入bigint型別
  CEILING       --舍入到最大整數   3.33舍入到4    2.98舍入到3    -3.61舍入到-3
  FLOOR()       --舍入到最小整數   3.33舍入到3    2.98舍入到2    -3.61舍入到-4
3.map(key1, value1, key2, value2, …)通過指定的鍵/值對,建立一個map

4.cast(expr as <type>)型別轉換。例如將字元”1″轉換為整數:cast(’1′ as bigint),如果轉換失敗返回NULL。
  例:CAST(num*100 AS decimal(8,0)) as num

5.unix_timestamp()  --如果不帶引數的呼叫,返回一個Unix時間戳(從’1970- 01 – 0100:00:00′到現在的UTC秒數)
   --指定日期引數呼叫UNIX_TIMESTAMP(),它返回引數值’1970- 01 – 0100:00:00′到指定日期的秒數
  unix_timestamp(string date, string pattern)   --指定時間輸入格式,返回到1970年秒數:unix_timestamp(’2009-03-20′, ‘yyyy-MM-dd’) = 1237532400
  from_unixtime(bigint unixtime[, string format]) 
    例:select from_unixtime(1505750400,'%Y-%m-%d %H-%i-%S');
  --UNIX_TIMESTAMP引數表示返回一個值’YYYY- MM – DD HH:MM:SS’或YYYYMMDDHHMMSS.uuuuuu格式,這取決於是否是在一個字串或數字語境中
  to_date(string timestamp)    --返回時間中的年月日: to_date(“1970-01-01 00:00:00″) = “1970-01-01″
  to_dates(string date)     --給定一個日期date,返回一個天數(0年以來的天數)
  year、month、day、hour、minute、second、weekofyear    --日期轉年、轉月…………
  
  hour  --返回指定時間的小時,範圍為0-23  
  weekofyear(string date)   --返回指定日期所在一年中的星期號,範圍0到53
  datediff('string enddate','string startdate')     --兩個時間引數的日期之差
  DATEDIFF ( date-part, date-expression-1, date-expression-2 )      --返回兩個日期之間的間隔
  date-part : year | quarter | month | week | day | hour | minute | second | millisecond
  sec_to_time(秒)    --將秒轉化成時間
  time_to_sec(時間)   --將時間轉化為秒
  date_add(string startdate,int days)       --給定時間,在此基礎上加上指定的時間段
  date_sub(string startdate,int days)       --給定時間,在此基礎上減去指定的時間段
  
6.CASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END    --當a=b時,返回c;當a=d時,返回e,否則返回f
  CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END      --當值為a時返回b,當值為c時返回d。否則返回e
  
7.concat(string A, string B…)   --連線多個字串,合併為一個字串,可以接受任意數量的輸入字串
                                --任何字元與null連線都是NULL
  concat_ws(string SEP, string A, string B…)    --帶分隔符字串連線函式
  例如:select concat_ws('_','abc','def','gh') from lxw_dual;返回 abc_def_gh

  行轉列,e.g. select concat_ws('_',collect_set(visitor_name))


8.upper(string A) 或者 ucase(string A)   --將文字字串轉換成字母全部大寫形式
9.lower(string A) 或者 lcase(string A)   --將文字字串轉換成字母全部小寫形式
10.trim(string A)   --刪除字串兩端的空格,字元之間的空格保留
   ltrim   --左邊去空格
   rtrim   --右邊去空格

11.like     --例如:a like b --如果字串A或者字串B為NULL,則返回NULL;如果字串A符合表示式B  的正則語法,則為TRUE;否則為FALSE。
            --B中字元”_”表示任意單個字元,而字元”%”表示任意數量的字元。
   例如:select aaaaaa like '%aaa%'

12.split(string str, string pat)    --將字串轉換為陣列,以pat為分隔

13.substr(string A, int start) 或者 substring(string A, int start) --字串擷取函式,
   例:select substr(‘abcde’,3);  --返回cde
   例:select substring('ancdefghijklmn',4,8);    --返回 defghijk     
   
    該子字串從指定的 beginIndex 處開始, endIndex:到指定的 endIndex-1處結束。   


14.regexp_extract    --正則表示式解析函式  通過下標返回正則表示式指定的部分
regexp_extract(str, regexp[, idx])
其中:
str是被解析的字串
regexp 是正則表示式
idx是返回結果 取表示式的哪一部分  預設值為1。
0表示把整個正則表示式對應的結果全部返回,1表示返回正則表示式中第一個() 對應的結果 以此類推 
例 from 
     (select distinct id,      name,   val   from text_table
      where p_provincecode=12345    and regexp_extract(lower(id),'(@id)$|(@num)(\\d*)$',0) <>''
     )a
$   匹配行結束符;
*   匹配0或多個正好在它之前的那個字元;重複零次或多次
\   這是引用符,用來將這裡列出的這些元字元當作普通的字元來進行匹配;
|   將兩個匹配條件進行邏輯“或”(Or)運算;
\d  匹配數字。在hive這種寫正則表示式需要用\轉義,所以\\d
^   匹配一行的開始
?   匹配0或1個正好在它之前的那個字元;重複零次或一次
.   匹配除換行符號外的任意字元

15.regexp_replace(string A, string B, string C)    --正則表示式替換函式 字串A中的B字元被C字元替代
regexp_replace(trim(waitbegin), '/', '-')

unix_timestamp(concat_ws(':', regexp_replace(trim(ackbegin), '/', '-'), '00'))-unix_timestamp(concat_ws(':', regexp_replace(trim(waitbegin), '/', '-'), '00')) as wait_duration,

16.get_json_object(string json_string, string path)  --json解析函式  解析json的字串json_string,返回path指定的內容。如果輸入的json字串無效,那麼返回NULL。

17.內建聚合函式  count、sum、avg、min、max

18.left semi join ... on ...--只打印左邊的表中的列,規律是如果主鍵在右邊表中存在,則列印,否則過濾掉
--相當於sql的in
--不會產生重複的多條記錄

19.collect_set --與group by組合能列轉行,相當於group_concat
20.SELECT  COALESCE(NULL, NULL, GETDATE())  --由於兩個引數都為null,所以返回getdate()函式的值,也就是當前時間。即返回第一個非空的值。由於這個函式是返回第一個非空的值,所以引數裡面必須最少有一個非空的值,如不是,將會報錯

sql:注意問題
1.hive中只有union 沒有union all
union --聯合兩張表(會自動去重,兩張表取出的欄位個數和型別必須一致)    並集操作
union all  --聯合兩張表的所有資料(不會去重,兩張表取出的欄位個數和型別必須一致)     並集操作

2.ABS() --求絕對值
  
3.與over函式結合的幾個函式介紹
參考網址:http://blog.csdn.net/winer2008/article/details/4283539
row_number()over()、rank()over()和dense_rank()over()函式的使用
  row_number() 是沒有重複值的排序(即使兩天記錄相等也是不重複的),可以利用它來實現分頁
  dense_rank() 是連續排序,兩個第二名仍然跟著第三名
  rank()       是跳躍排序,兩個第二名下來就是第四名

row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 
--表示根據COL1分組,在分組內部根據 COL2排序,而此函式計算的值就表示每組內部排序後的順序編號(組內連續的唯一的)
例:row_number() over (partition BY stbid,userid ORDER BY timestamp) AS group_idx,

--over(order by salary range between 5 preceding and 5 following):視窗範圍為當前行資料幅度減5加5後的範圍內的。
sum(s)over(order by s range between 2 preceding and 2 following) 表示加2或2的範圍內的求和

--over(order by salary rows between 5 preceding and 5 following):視窗範圍為當前行前後各移動5行。
sum(s)over(order by s rows between 2 preceding and 2 following)表示在上下兩行之間的範圍內
4.group by 和 having
SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2

歡迎關注,更多福利

這裡寫圖片描述