《極限競速:地平線5》新增敞篷車及野生動物
阿新 • • 發佈:2021-07-12
hive 架構
hive 資料型別分基本資料型別 和集合資料型別
隱式轉換:
hive> select '1.0'+2; // 數字字串轉double OK 3.0 hive> select '1111' > 10; hive> select 1 > 0.8;
顯式轉換:
hive> select cast('1111s' as int); OK NULL hive> select cast('1111' as int); OK 1111
集合資料型別:
集合測試:
hive> select array(1,2,3); OK [1,2,3] -- 使用 [] 訪問陣列元素 hive> select arr[0] from (select array(1,2,3) arr) tmp; hive> select map('a', 1, 'b', 2, 'c', 3); OK {"a":1,"b":2,"c":3} -- 使用 [] 訪問map元素 hive> select mymap["a"] from (select map('a', 1, 'b', 2, 'c', 3) as mymap) tmp; -- 使用 [] 訪問map元素。 key 不存在返回 NULL hive> select mymap["x"] from (select map('a', 1, 'b', 2, 'c', 3) as mymap) tmp; NULL hive> select struct('username1', 7, 1288.68); OK {"col1":"username1","col2":7,"col3":1288.68} -- 給 struct 中的欄位命名 hive> select named_struct("name", "username1", "id", 7, "salary", 12880.68); OK {"name":"username1","id":7,"salary":12880.68} -- 使用 列名.欄位名 訪問具體資訊 hive> select userinfo.id > from (select named_struct("name", "username1", "id", 7, "salary", 12880.68) userinfo) tmp; -- union 資料型別 hive> select create_union(0, "zhansan", 19, 8000.88) uinfo;
Hive 預設分隔符:
Hive DDL:
建立資料庫:
-- 建立資料庫,在HDFS上儲存路徑為 /user/hive/warehouse/*.db hive (default)> create database mydb; hive (default)> dfs -ls /user/hive/warehouse; -- 避免資料庫已經存在時報錯,使用 if not exists 進行判斷【標準寫法】 hive (default)> create database if not exists mydb; -- 建立資料庫。新增備註,指定資料庫在存放位置 hive (default)> create database if not exists mydb2 comment 'this is mydb2' location '/user/hive/mydb2.db';
檢視資料庫:
-- 檢視所有資料庫 show database; -- 檢視資料庫資訊 desc database mydb2; desc database extended mydb2; describe database extended mydb2;
使用資料庫:
use mydb;
刪除資料庫:
-- 刪除一個空資料庫 drop database databasename; -- 如果資料庫不為空,使用 cascade 強制刪除 drop database databasename cascade; //慎用,防止刪庫跑路
建立表:
語法:
create [external] table [IF NOT EXISTS] table_name [(colName colType [comment 'comment'], ...)] [comment table_comment] [partition by (colName colType [comment col_comment], ...)] [clustered BY (colName, colName, ...) [sorted by (col_name [ASC|DESC], ...)] into num_buckets buckets] [row format row_format] [stored as file_format] [LOCATION hdfs_path] [TBLPROPERTIES (property_name=property_value, ...)] [AS select_statement]; CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name LIKE existing_table_or_view_name [LOCATION hdfs_path];
欄位解釋:
1. CREATE TABLE。按給定名稱建立表,如果表已經存在則丟擲異常。可使用if not exists 規避。 2. EXTERNAL關鍵字。建立外部表,否則建立的是內部表(管理表)。 刪除內部表時,資料和表的定義同時被刪除; 刪除外部表時,僅僅刪除了表的定義,資料保留; 在生產環境中,多使用外部表; 3. comment。表的註釋 4. partition by。對錶中資料進行分割槽,指定表的分割槽欄位 5. clustered by。建立分桶表,指定分桶欄位 6. sorted by。對桶中的一個或多個列排序,較少使用
儲存子句:
ROW FORMAT DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
7.stored as TEXTFILE ORC PARQUET
8.LOCATION。表在HDFS上的存放位置
9.AS。後面可以接查詢語句,表示根據後面的查詢結果建立表
create table xxx as select ... 這種方式不會複製分割槽,分桶
10.like 複製表結構,不復制資料
內部表 & 外部表:
- 內部表、管理表 表和資料繫結,一起刪除
- 外部表,刪除表不影響資料
-- 內部錶轉外部表 alter table t1 set tblproperties('EXTERNAL'='TRUE'); -- 查詢表資訊,是否轉換成功 desc formatted t1; -- 外部錶轉內部表。EXTERNAL 大寫,false 不區分大小 alter table t1 set tblproperties('EXTERNAL'='FALSE'); -- 查詢表資訊,是否轉換成功 desc formatted t1;
分割槽表:
為了避免全表掃描,將資料儲存在不同子目錄中,每個子目錄對應一個分割槽
分割槽表建立與資料載入示例:
-- 建立表 create table if not exists t3( id int ,name string ,hobby array<string> ,addr map<String,string> ) partitioned by (dt string) row format delimited fields terminated by ';' collection items terminated by ',' map keys terminated by ':'; -- 載入資料。 load data local inpath "/home/hadoop/data/t1.dat" into table t3 partition(dt="2020-06-01"); load data local inpath "/home/hadoop/data/t1.dat" into table t3 partition(dt="2020-06-02");
備註:分割槽欄位不是表中已經存在的資料,可以將分割槽欄位看成偽列
檢視分割槽:
show partitions t3;
新增分割槽並設定資料:
-- 增加一個分割槽,不載入資料 alter table t3 add partition(dt='2020-06-03'); -- 增加多個分割槽,不載入資料 alter table t3 add partition(dt='2020-06-05') partition(dt='2020-06-06'); -- 增加多個分割槽。準備資料 hdfs dfs -cp /user/hive/warehouse/mydb.db/t3/dt=2020-06-01 /user/hive/warehouse/mydb.db/t3/dt=2020-06-07 hdfs dfs -cp /user/hive/warehouse/mydb.db/t3/dt=2020-06-01 /user/hive/warehouse/mydb.db/t3/dt=2020-06-08 -- 增加多個分割槽。載入資料 alter table t3 add partition(dt='2020-06-07') location '/user/hive/warehouse/mydb.db/t3/dt=2020-06-07' partition(dt='2020-06-08') location '/user/hive/warehouse/mydb.db/t3/dt=2020-06-08'; -- 查詢資料 select * from t3
修改分割槽的hdfs 路徑:
alter table t3 partition(dt='2020-06-01') set location '/user/hive/warehouse/t3/dt=2020-06-03';
刪除分割槽:
-- 可以刪除一個或多個分割槽,用逗號隔開 alter table t3 drop partition(dt='2020-06-03'), partition(dt='2020-06-04');
分桶表:
當單個的分割槽或者表的資料量過大,分割槽不能更細粒度的劃分資料,就需要使用分桶。
分桶原理:分桶欄位.hashCode % 分桶個數
分桶表測試:
create table course( id int, name string, score int ) clustered by (id) into 3 buckets row format delimited fields terminated by "\t";
-- 建立普通表 create table course_common( id int, name string, score int ) row format delimited fields terminated by "\t"; -- 普通表載入資料 load data local inpath '/home/hadoop/data/course.dat' into table course_common; -- 通過 insert ... select ... 給桶表載入資料 insert into table course select * from course_common; -- 觀察分桶資料。資料按照:(分割槽欄位.hashCode) % (分桶數) 進行分割槽
備註:
- 分桶規則:分桶欄位.hashCode % 分桶數
- 分桶表載入資料時,使用 insert... select ... 方式進行
- 網上有資料說要使用分割槽表需要設定 hive.enforce.bucketing=true,那是Hive 1.x 以前的版本;Hive 2.x 中,刪除了該引數,始終可以分桶;
修改表 & 刪除表:
-- 修改表名。rename alter table course_common rename to course_common1; -- 修改列名。change column alter table course_common1 change column id cid int; -- 修改欄位型別。change column alter table course_common1 change column cid cid string; -- The following columns have types incompatible with the existing columns in their respective positions -- 修改欄位資料型別時,要滿足資料型別轉換的要求。如int可以轉為string,但是 string不能轉為int -- 增加欄位。add columns alter table course_common1 add columns (common string); -- 刪除欄位:replace columns -- 這裡僅僅只是在元資料中刪除了欄位,並沒有改動hdfs上的資料檔案 alter table course_common1 replace columns( id string, cname string, score int); -- 刪除表 drop table course_common1;
資料匯入:
語法:
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
- LOCAL:
- LOAD DATA LOCAL ... 從本地檔案系統載入資料到Hive表中。本地檔案會拷 貝到Hive表指定的位置
- LOAD DATA ... 從HDFS載入資料到Hive表中。HDFS檔案移動到Hive表指定 的位置
- INPATH:載入資料的路徑
- OVERWRITE:覆蓋表中已有資料;否則表示追加資料
- PARTITION:將資料載入到指定的分割槽
插入資料:
常用於從普通表插入資料到分割槽表,或orc ,parquet 儲存格式的表
-- 插入資料 insert into table tabC partition(month='202001') values (5, 'wangwu', 'BJ'), (4, 'lishi', 'SH'), (3, 'zhangsan', 'TJ'); -- 插入查詢的結果資料 insert into table tabC partition(month='202002') select id, name, area from tabC where month='202001'; -- 多表(多分割槽)插入模式 from tabC insert overwrite table tabC partition(month='202003') select id, name, area where month='202002' insert overwrite table tabC partition(month='202004') select id, name, area where month='202002'; // from 提前,這樣可以減少hive sql的stage
建立表並插入資料:
-- 根據查詢結果建立表 create table if not exists tabD as select * from tabC;
資料匯出:
-- 將查詢結果匯出到本地 insert overwrite local directory '/home/hadoop/data/tabC' select * from tabC; -- 將查詢結果格式化輸出到本地 insert overwrite local directory '/home/hadoop/data/tabC2' row format delimited fields terminated by ' ' select * from tabC; -- 將查詢結果匯出到HDFS insert overwrite directory '/user/hadoop/data/tabC3' row format delimited fields terminated by ' ' select * from tabC; -- dfs 命令匯出資料到本地。本質是執行資料檔案的拷貝 dfs -get /user/hive/warehouse/mydb.db/tabc/month=202001 /home/hadoop/data/tabC4
-- hive 命令匯出資料到本地。執行查詢將查詢結果重定向到檔案 hive -e "select * from tabC" > a.log -- export 匯出資料到HDFS。使用export匯出資料時,不僅有數還有表的元資料信 息 export table tabC to '/user/hadoop/data/tabC4'; -- export 匯出的資料,可以使用 import 命令匯入到 Hive 表中 -- 使用 like tname建立的表結構與原表一致。create ... as select ... 結構可能不一致 create table tabE like tabc; import table tabE from ''/user/hadoop/data/tabC4'; -- 截斷表,清空資料。(注意:僅能操作內部表) truncate table tabE; -- 以下語句報錯,外部表不能執行 truncate 操作 alter table tabC set tblproperties("EXTERNAL"="TRUE"); truncate table tabC;
Hive DQL :
SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition] [GROUP BY col_list] [ORDER BY col_list] [CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list]] [LIMIT [offset,] rows]
基本查詢:
-- 省略from子句的查詢 select 8*888 ; select current_date ; -- 使用列別名 select 8*888 product; select current_date as currdate; -- 全表查詢 select * from emp; -- 選擇特定列查詢 select ename, sal, comm from emp; -- 使用函式 select count(*) from emp; -- count(colname) 按欄位進行count,不統計NULL select sum(sal) from emp; select max(sal) from emp; select min(sal) from emp; select avg(sal) from emp; -- 使用limit子句限制返回的行數 select * from emp limit 3;
where 子句:
where 字句中不能使用列的別名
rlike 可以寫正則表示式。
group by 字句:
-- 計算emp表每個部門的平均工資 select deptno, avg(sal) from emp group by deptno; -- 計算emp每個部門中每個崗位的最高薪水 select deptno, job, max(sal) from emp group by deptno, job;
- where 針對表資料過濾
- having 針對group by的結果過濾
- group by 中不能使用別名
表連線:
1. 內連線: [inner] join 2. 外連線 (outer join) - 左外連線。 left [outer] join,左表的資料全部顯示 - 右外連線。 right [outer] join,右表的資料全部顯示 - 全外連線。 full [outer] join,兩張表的資料都顯示
排序字句:
全域性排序 order by :
- order by 子句出現在select語句的結尾;
- order by子句對最終的結果進行排序;
- 預設使用升序(ASC);可以使用DESC,跟在欄位名之後表示降序;
ORDER BY執行全域性排序,只有一個reduce;
-- 普通排序 select * from emp order by deptno; -- 按別名排序 select empno, ename, job, mgr, sal + nvl(comm, 0) salcomm, deptno from emp order by salcomm desc; -- 多列排序 select empno, ename, job, mgr, sal + nvl(comm, 0) salcomm, deptno from emp order by deptno, salcomm desc; -- 排序欄位要出現在select子句中。以下語句無法執行(因為select子句中缺少 deptno): select empno, ename, job, mgr, sal + nvl(comm, 0) salcomm from emp order by deptno, salcomm desc;
注意排序欄位需要出現在select語句中。
分割槽排序(distribute by):
結合sort by 使用。 使得結果分割槽內有序。
-- 啟動2個reducer task;先按 deptno 分割槽,在分割槽內按 sal+comm 排序 set mapreduce.job.reduces=2; -- 將結果輸出到檔案,觀察輸出結果 insert overwrite local directory '/home/hadoop/output/distBy' select empno, ename, job, deptno, sal + nvl(comm, 0) salcomm from emp distribute by deptno sort by salcomm desc;
當distribute by 與 sort by是同一個欄位時,可使用cluster by簡化語法;
cluster by 只能是升序,不能指定排序規則;
-- 語法上是等價的 select * from emp distribute by deptno sort by deptno; select * from emp cluster by deptno;
Hive 函式:
-- 顯示自帶函式的用法 desc function upper; desc function extended upper;
日期相關函式:
-- 當前前日期 select current_date; select unix_timestamp(); -- 建議使用current_timestamp,有沒有括號都可以 select current_timestamp(); -- 時間戳轉日期 select from_unixtime(1505456567); select from_unixtime(1505456567, 'yyyyMMdd'); select from_unixtime(1505456567, 'yyyy-MM-dd HH:mm:ss'); -- 日期轉時間戳 select unix_timestamp('2019-09-15 14:23:00'); -- 計算時間差 select datediff('2020-04-18','2019-11-21'); select datediff('2019-11-21', '2020-04-18'); -- 查詢當月第幾天 select dayofmonth(current_date); -- 計算月末: select last_day(current_date); -- 當月第1天: select date_sub(current_date, dayofmonth(current_date)-1) -- 下個月第1天: select add_months(date_sub(current_date, dayofmonth(current_date)-1), 1) -- 字串轉時間(字串必須為:yyyy-MM-dd格式) select to_date('2020-01-01'); select to_date('2020-01-01 12:12:12'); -- 日期、時間戳、字串型別格式化輸出標準時間格式 select date_format(current_timestamp(), 'yyyy-MM-dd HH:mm:ss'); select date_format(current_date(), 'yyyyMMdd'); select date_format('2020-06-01', 'yyyy-MM-dd HH:mm:ss');
-- 計算emp表中,每個人的工齡
select *, round(datediff(current_date, hiredate)/365,1) workingyears from emp;
字串相關函式:
-- 轉小寫。lower select lower("HELLO WORLD"); -- 轉大寫。upper select lower(ename), ename from emp; -- 求字串長度。length select length(ename), ename from emp; -- 字串拼接。 concat / || select empno || " " ||ename idname from emp; select concat(empno, " " ,ename) idname from emp; -- 指定分隔符。concat_ws(separator, [string | array(string)]+) SELECT concat_ws('.', 'www', array('lagou', 'com')); select concat_ws(" ", ename, job) from emp; -- 求子串。substr SELECT substr('www.lagou.com', 5); SELECT substr('www.lagou.com', -5); SELECT substr('www.lagou.com', 5, 5); -- 字串切分。split,注意 '.' 要轉義 select split("www.lagou.com", "\\.");
數學相關函式:
-- 四捨五入。round select round(314.15926); select round(314.15926, 2); select round(314.15926, -2); -- 向上取整。ceil select ceil(3.1415926); -- 向下取整。floor select floor(3.1415926);
條件函式:
-- if (boolean testCondition, T valueTrue, T valueFalseOrNull) select sal, if (sal<1500, 1, if (sal < 3000, 2, 3)) from emp; -- CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END -- 將emp表的員工工資等級分類:0-1500、1500-3000、3000以上 select sal, if (sal<=1500, 1, if (sal <= 3000, 2, 3)) from emp; -- CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END -- 複雜條件用 case when 更直觀 select sal, case when sal<=1500 then 1 when sal<=3000 then 2 else 3 end sallevel from emp; -- 以下語句等價 select ename, deptno, case deptno when 10 then 'accounting' when 20 then 'research' when 30 then 'sales' else 'unknown' end deptname from emp; select ename, deptno, case when deptno=10 then 'accounting' when deptno=20 then 'research' when deptno=30 then 'sales' else 'unknown' end deptname from emp; -- COALESCE(T v1, T v2, ...)。返回引數中的第一個非空值;如果所有值都為 NULL,那麼返回NULL select sal, coalesce(comm, 0) from emp; -- isnull(a) isnotnull(a) select * from emp where isnull(comm); select * from emp where isnotnull(comm); -- nvl(T value, T default_value) // 如果value 為null,則賦值 default_value
select empno, ename, job, mgr, hiredate, deptno, sal + nvl(comm,0) sumsal from emp;
-- nullif(x, y) 相等為空,否則為a
SELECT nullif("b", "b"), nullif("b", "a");
UDTF 函式:
一行輸 入,多行輸出。