数据仓库-Hive
1.數據倉庫的基本概念
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-v0OhlHVi-1616598779764)(…/TypoarWrokPath/images/1615604642904.png)]
數據倉庫的特性
數據倉庫是面向主題的(Subject-Oriented )、集成的(Integrated)、非易失的(Non-Volatile)和時變的(Time-Variant )數據集合,用以支持管理決策。
1.2.1. 面向主題
數據倉庫是面向主題的,數據倉庫通過一個個主題域將多個業務系統的數據加載到一起,為了各個主題(如:用戶、訂單、商品等)進行分析而建,操作型數據庫是為了支撐各種業務而建立。
1.2.2. 集成性
數據倉庫會將不同源數據庫中的數據匯總到一起,數據倉庫中的綜合數據不能從原有的數據庫系統直接得到。因此在數據進入數據倉庫之前,必然要經過統一與整合,這一步是數據倉庫建設中最關鍵、最復雜的一步(ETL),要統一源數據中所有矛盾之處,如字段的同名異義、異名同義、單位不統一、字長不一致,等等。
1.2.3. 非易失性
操作型數據庫主要服務于日常的業務操作,使得數據庫需要不斷地對數據實時更新,以便迅速獲得當前最新數據,不至于影響正常的業務運作。在數據倉庫中只要保存過去的業務數據,不需要每一筆業務都實時更新數據倉庫,而是根據商業需要每隔一段時間把一批較新的數據導入數據倉庫。 數據倉庫的數據反映的是一段相當長的時間內歷史數據的內容,是不同時點的數據庫的集合,以及基于這些快照進行統計、綜合和重組的導出數據。數據倉庫中的數據一般僅執行查詢操作,很少會有刪除和更新。但是需定期加載和刷新數據。
1.2.4. 時變性
數據倉庫包含各種粒度的歷史數據。數據倉庫中的數據可能與某個特定日期、星期、月份、季度或者年份有關。數據倉庫的目的是通過分析企業過去一段時間業務的經營狀況,挖掘其中隱藏的模式。雖然數據倉庫的用戶不能修改數據,但并不是說數據倉庫的數據是永遠不變的。分析的結果只能反映過去的情況,當業務變化后,挖掘出的模式會失去時效性。因此數據倉庫的數據需要定時更新,以適應決策的需要。
2數據庫與數據倉庫的區別
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lmCOsEPg-1616598779768)(…/TypoarWrokPath/images/1615605202339.png)]
3. 數倉的分層架構
數據倉庫的數據來源于不同的源數據,并提供多樣的數據應用,數據自下而上流入數據倉庫后向上層開放應用,而數據倉庫只是中間集成化數據管理的一個平臺。
源數據層(ODS)`:
? 此層數據無任何更改,直接沿用外圍系統數據結構和數據,不對外開放;為臨時存儲層,是接口數據的臨時存儲區域,為后一步的數據處理做準備。
數據倉庫層(DW)`:
? 也稱為細節層,DW層的數據應該是一致的、準確的、干凈的數據,即對源系統數據進行了清洗(去除了雜質)后的數據。
數據應用層(DA或APP)`:
? 前端應用直接讀取的數據源;根據報表、專題分析需求而計算生成的數據。
數據倉庫從各數據源獲取數據及在數據倉庫內的數據轉換和流動都可以認為是ETL(抽取Extra, 轉化Transfer, 裝載Load)的過程,ETL是數據倉庫的流水線,也可以認為是數據倉庫的血液,它維系著數據倉庫中數據的新陳代謝,而數據倉庫日常的管理和維護工作的大部分精力就是保持ETL的正常和穩定。
為什么要對數據倉庫分層?
用空間換時間,通過大量的預處理來提升應用系統的用戶體驗(效率),因此數據倉庫會存在大量冗余的數據;不分層的話,如果源業務系統的業務規則發生變化將會影響整個數據清洗過程,工作量巨大。
通過數據分層管理可以簡化數據清洗的過程,因為把原來一步的工作分到了多個步驟去完成,相當于把一個復雜的工作拆成了多個簡單的工作,把一個大的黑盒變成了一個白盒,每一層的處理邏輯都相對簡單和容易理解,這樣我們比較容易保證每一個步驟的正確性,當數據發生錯誤的時候,往往我們只需要局部調整某個步驟即可。
數倉的元數據管理
元數據(Meta Date),主要記錄數據倉庫中模型的定義、各層級間的映射關系、監控數據倉庫的數據狀態及ETL的任務運行狀態。一般會通過元數據資料庫(Metadata Repository)來統一地存儲和管理元數據,其主要目的是使數據倉庫的設計、部署、操作和管理能達成協同和一致。
元數據是數據倉庫管理系統的重要組成部分,元數據管理是企業級數據倉庫中的關鍵組件,貫穿數據倉庫構建的整個過程,直接影響著數據倉庫的構建、使用和維護。
構建數據倉庫的主要步驟之一是ETL。這時元數據將發揮重要的作用,它定義了源數據系統到數據倉庫的映射、數據轉換的規則、數據倉庫的邏輯結構、數據更新的規則、數據導入歷史記錄以及裝載周期等相關內容。數據抽取和轉換的專家以及數據倉庫管理員正是通過元數據高效地構建數據倉庫。
- 用戶在使用數據倉庫時,通過元數據訪問數據,明確數據項的含義以及定制報表。
- 數據倉庫的規模及其復雜性離不開正確的元數據管理,包括增加或移除外部數據源,改變數據清洗方法,控制出錯的查詢以及安排備份等。
元數據可分為技術元數據和業務元數據。技術元數據為開發和管理數據倉庫的IT 人員使用,它描述了與數據倉庫開發、管理和維護相關的數據,包括數據源信息、數據轉換描述、數據倉庫模型、數據清洗與更新規則、數據映射和訪問權限等。而業務元數據為管理層和業務分析人員服務,從業務角度描述數據,包括商務術語、數據倉庫中有什么數據、數據的位置和數據的可用性等,幫助業務人員更好地理解數據倉庫中哪些數據是可用的以及如何使用。
由上可見,元數據不僅定義了數據倉庫中數據的模式、來源、抽取和轉換規則等,而且是整個數據倉庫系統運行的基礎,元數據把數據倉庫系統中各個松散的組件聯系起來,組成了一個有機的整體。
Hive的基本概念
什么是 Hive
Hive是基于Hadoop的一個數據倉庫工具,可以將****結構化的數據****文件映射為一張數據庫表,并提供類SQL查詢功能。其本質是將SQL轉換為MapReduce的任務進行運算,底層由HDFS來提供數據的存儲,說白了hive可以理解為一個將SQL轉換為MapReduce的任務的工具,甚至更進一步可以說hive就是一個MapReduce的客戶端
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tvSdHLGv-1616598779771)(…/TypoarWrokPath/images/1615646634160.png)]
為什么使用 Hive
1.采用類SQL語法去操作數據,提供快速開發的能力。
2.避免了去寫MapReduce,減少開發人員的學習成本。
3.功能擴展很方便。
Hive的架構
用戶接口
包括CLI、JDBC/ODBC、WebGUI。其中,CLI(command line interface)為shell命令行;JDBC/ODBC是Hive的JAVA實現,與傳統數據庫JDBC類似;WebGUI是通過瀏覽器訪問Hive。
元數據存儲
通常是存儲在關系數據庫如mysql/derby中。Hive 將元數據存儲在數據庫中。Hive 中的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否為外部表等),表的數據所在目錄等。
解釋器、編譯器、優化器、執行器:
完成HQL 查詢語句從詞法分析、語法分析、編譯、優化以及查詢計劃的生成。生成的查詢計劃存儲在HDFS 中,并在隨后有MapReduce 調用執行。
5.查看日志方法
進入到日志的目錄里面,使用命令 tail -f hive.log
6.HIVE的sql執行原理
是通過sql語句去解析元數據,根據元數據找到HDFS的路徑,找到對應的內容
select * from test :在hive中的解釋;from 就會先去找元數據如果存在就會通過元數據提供的路徑到HDFS的路徑,然后把把表名拼接上去,就形成了一個完整的hdfs路徑,就可以在hdfs中找到對應的內容
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-H4EDchAG-1616598779773)(…/TypoarWrokPath/images/1615734204375.png)]
7.使用jdbc連接
都要在hive目錄下執行
1.開啟metastore
bin/hive --service metastore
2.開啟hiveserver2
bin/hive --service hiveserver2
3.連接jdbc
bin/beeline -u jdbc:hive2://hadoop102:10000 -n atguigu
8.執行報錯bin/beeline -u jdbc:hive2://hadoop102:10000 -n atguigu
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dNG6E87k-1616598779775)(…/TypoarWrokPath/images/1615740629757.png)]
解決方案在hadoop 的etc下面hadoop的coer.site.xml中加入如下配置
atguigu根據你自己的用戶組來定
hadoop.proxyuser.atguigu.hosts * <property><name>hadoop.proxyuser.atguigu.groups</name><value>*</value> </property>9.日志位置
cd/tmp/atguigu tail -f hive 實時監控日志
10.查看進程
1.查看元數據服務進程
-v 表示不包含grep自己
ps -ef |grep -v grep |grep -i HiveMetastore
2.獲取端口號
awk 表示根據空格進行拆分
$2 代表下標為二的
ps -ef |grep -v grep |grep -i HiveMetastore |awk ‘{print $2}’
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uer9VxWW-1616598779776)(…/TypoarWrokPath/images/1615743414567.png)]
11.解決中文亂碼問題
# 創建表(row format delimited fields terminated by '\t')插入數據格式以'\t'分隔 create table teacher(t_id string,t_name string) row format delimited fields terminated by '\t' create table course(c_id string,c_course string,t_id string) row format delimited fields terminated by '\t' create table score(s_id string,c_id string,s_score string) row format delimited fields terminated by '\t' create table student(s_id string,s_name string,s_birth date,s_sex string) row format delimited fields terminated by '\t' # 以這種方式導入數據不會導致中文亂碼 插入對應格式數據 'hdfs://用戶名:8020/路徑+文件名' 插入完成文件會丟失 LOAD DATA INPATH 'hdfs://singlenode:8020/Hive/school/teacher.txt' INTO TABLE teacher;12.操作集合類型案列
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XJm0UCDw-1616598779778)(…/TypoarWrokPath/images/1615833288281.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lx30Uep0-1616598779778)(…/TypoarWrokPath/images/1615833308561.png)]
1案列操作
//(1)假設某表有如下一行,我們用 JSON 格式來表示其數據結構。在 Hive 下訪問的格式為 {"name": "songsong","friends": ["bingbing" , "lili"] , //列表 Array, "children": { //鍵值 Map,"xiao song": 18 ,"xiaoxiao song": 19}"address": { //結構 Struct,"street": "hui long guan","city": "beijing"} } //創建本地測試文件 test.txt 上傳到hdsf文件系統中 路徑/user/hive/warehouse/mydata.db/test01 songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing //創建表 create table test01(name string,friends array<string>,children map<string, int>,address struct<street:string, city:string> )row format delimited fields terminated by ',' //列分隔符collection items terminated by '_' //MAP STRUCT 和 ARRAY 的分隔符(數據分割符號)map keys terminated by ':' //map內部分隔符lines terminated by '\n'; //行分隔符 //查詢array集合 ,和java一樣根據下標查詢 select friends[0] from test01; //查詢map鍵值對 select children['xiao song'] from test01;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-z7JIetB0-1616598779779)(…/TypoarWrokPath/images/1615833636777.png)]
13.hive的外部表和內部表
1.外部表和內部表區別
14.數據導入\導出方式
1.使用本地文件插入表數據
load data local inpath ‘/opt/employee.txt’ into table employee; #以copy的方式導入數據
2.使用HDFS 的文件插入表數據
load data inpath ‘hdfs://sinlenode:8020/root/data/employee.txt’ into table emp.employee_ext; #沒有local,使用hdfs上的mv命令導入數據
3.使用insert插入數據
insert overwrite table student_par select id, name from student where month=‘201709’;
insert into:以追加數據的方式插入到表或分區,原有數據不會刪除
insert overwrite:會覆蓋表中已存在的數據
注意:
Hive支持從同一個表進行多次插入
INSERT INTO中TABLE關鍵字是可選的
INSERT INTO可以指定插入到哪些字段中
如:INSERT INTO t(x,y,z)
INSERT INTO table_name VALUES,支持插入值列表
數據插入必須與指定列數相同
4.多表(多分區)插入模式(根據多張表查詢結果)
from student insert overwrite table student partition(month='201707') select id, name where month='201709' insert overwrite table student partition(month='201706') select id, name where month='201709';5.如果有分區的導入方式
-- LOCAL表示文件位于本地,OVERWRITE表示覆蓋現有數據 LOAD DATA LOCAL INPATH '/home/dayongd/Downloads/employee.txt' OVERWRITE INTO TABLE employee_partitioned PARTITION (year=2014, month=12);6.export / import
1.將表的數據到入到hdfs 上面
export table order_items02 To '/order/export' ; --路徑必須不存在2.將導出的數據導入到表的里面
import table o_01 from '/order/export'; --表名可以不存在 o_01是表名可以不存在7.將hive數倉的數據導入到本地
--local 路徑用本地的路徑 overwrite表示覆蓋原來的數據 from order_items02 insert overwrite local directory '/opt/data/input/' select *; --沒有local 的就上傳到hdfs中文件夾可以不存在 from order_items02 insert overwrite directory '/opt/data/input/' select *; --加了overwirte 覆蓋 from order_items02 insert overwrite table order_itemstest '/opt/data/input/' select *;把值為null 的列放到最前面
--在使用left join(任何一種join只要有空值的時候就可以)的時候將列為null的放到最前面 order by asc升序 select * from customers cus left join orders ord on cus.customer_id=ord.customer_id order by order_id limit 30;把值為null 的列放到最后面
--在使用left join(任何一種join只要有空值的時候就可以)的時候將列為null的放到最前面 order by desc升序 select * from customers cus left join orders ord on cus.customer_id=ord.customer_id order by order_id desc;15.刪除包含有的數據
2、 使用 cascade 關鍵字 drop database if exists 數據庫名 cascade; 可以刪除包含有表的數據庫
3.數據出錯恢復 truncate table bigdata3.student; 可以讓索引回到1,清空所有的數據
4.HIVE高建表語句
1.CTAS – as select * from test 方式建表(會復制表結構和表數據)
2. 注:CTAS不能創建partition, external, bucket table
3.Like (只復制表結構,不復制表數據)
create table employee_like like employee;
16.union all 和 union 的區別
union和union all的區別是,union會自動壓縮多個結果集合中的重復結果,而union all則將所有的結果全部顯示出來,不管是不是重復。
Union:(兩張表的字段必須要是一樣的)對兩個結果集進行并集操作,不包括重復行,同時進行默認規則的排序;
UNION在進行表鏈接后會篩選掉重復的記錄,所以在表鏈接后會對所產生的結果集進行排序運算,刪除重復的記錄再返回結果。
實際大部分應用中是不會產生重復的記錄,最常見的是過程表與歷史表UNION
Union All:對兩個結果集進行并集操作,包括重復行,不進行排序;
如果返回的兩個結果集中有重復的數據,那么返回的結果集就會包含重復的數據了
注意:如果數據本身不存在重復數據 ,使用 union ,union all ,使用union all 的效率更高
select stu.*,c1.c_course,c1.s_score from school.student stu ,(select s_id,c_course,s_score from school.score s1,school.course cou where cou.c_id =1 and s1.c_id = cou.c_id ) c1 ,(select s_id,s_score from school.score s2 ,school.course cou where cou.c_id =2 and s2.c_id = cou.c_id) c2 where c1.s_id in (c2.s_id) and c1.s_score >c2.s_score and c1.s_id in (stu.s_id);17.使用WITH查詢
WITHc1 AS (select sco.s_id,sco.c_id,sco.s_score from school.score sco ,school.course cou where sco.c_id='01' and sco.c_id = cou.c_id),c2 AS (select sco.s_id,sco.c_id,sco.s_score from school.score sco,school.course cou where sco.c_id='02' and sco.c_id = cou.c_id)select stu.*,cc1.s_score from school.student stu,c1 cc1 ,c2 cc2 where cc1.s_id in (stu.s_id ) and cc1.s_id in (cc2.s_id) and cc1.s_score > cc2.s_score[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-JElVmCXv-1616598779781)(…/TypoarWrokPath/images/1615909392348.png)]
18.創建外部表 --external
1.要注意位置的順序
create external table employee(name string,work_place ARRAY<string>,sex_age STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)comment'這是一個員工表'row format delimited fields terminated by'|' --根據什么符號拆分collection items terminated by',' map keys terminated by ':' stored as textfile --指定文件的類型tblproperties ('skip.header.line.count'='1'); --去掉文件中頭部的N行數據,這里為1行location 'hdfs://singlenode132:8020/epm/employee';--指定外部表的存放位置1.創建完表之后修改表不讀取第一行
alter table customer set tblproperties ('skip.header.line.count'='1'); --設定不讀取數據中頭部的N行數據,這里為1行19查看表結構
1.desc fromatted 表名
desc formatted employee;20.查詢數據庫的詳情
desc database 數據庫名
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QksQrMJJ-1616598779782)(…/TypoarWrokPath/images/1615911476633.png)]
21.建表語法
--創建內部表 create external table employee(name string,work_place ARRAY<string>,sex_age STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)comment'這是一個員工表'row format delimited fields terminated by'|' --根據什么符號拆分collection items terminated by',' map keys terminated by ':' stored as textfile --指定文件的類型tblproperties ('skip.header.line.count'='1'); --去掉文件中頭部的N行數據,這里為1行location 'hdfs://singlenode132:8020/epm/employee';--指定外部表的存放位置--創建內部表 create table employee(name string,work_place ARRAY<string>,sex_age STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)comment'這是一個員工表' row format delimited fields terminated by'|' --根據什么符號拆分collection items terminated by',' --集合使用什么隔開的map keys terminated by ':' --map之間的隔開符stored as textfile --指定文件的類型tblproperties ('skip.header.line.count'='1'); --去掉文件中頭部的N行數據,這里為1行--使用 as select 建表create table 新表名 as select * from student;1.建完表之后修改屬性不讀取第一行
? alter table customer set tblproperties (‘skip.header.line.count’=‘1’); --設定不讀取數據中頭部的N行數據,這里為1行
22.內部表和外部表互相轉換
1.alter table 表名 set tblproperties(‘EXTERNAL’=‘TRUE’); FALSE 為內部表 TRUE 為外部表
alter table test02 set tblproperties(‘EXTERNAL’=‘TRUE’);
23.自定義分割符
create table test03(id int,name string ) row format delimited fields terminated by ‘,’ ;
24.修改表名
1.alter table 舊表名 rename to 新表名;
alter table test03 rename to test04;
25.修改列名
alter table 表名 change column 舊列名 新列名 新的數據類型; 如果舊列名是string類型的,就不能修改,因為string可以轉換為很多類型
2.alter table 表名 replace columns(deptno string, dname string, loc string); 所有的列都會被替換
1alter table dept change column deptdesc desc string;
2alter table dept replace columns(deptno string, dname string, loc string);
26.添加列名
1.alter table 表名 add columns(新增列名 類型);
alter table dept add columns(deptdesc string);
27.添加分區
分區是指分文件夾
1.靜態分區
開啟動態分區參數設置
1.開啟動態分區功能(默認 true,開啟)
hive.exec.dynamic.partition=true
2.設置為非嚴格模式(動態分區的模式,默認 strict,表示必須指定至少一個分區為
nonstrict 模式表示允許所有的分區字段都可以使用動態分區。)
hive.exec.dynamic.partition.mode=nonstrict
hadoop 新增分區功能
--創建一張表指定分區一個字段 create table dept_no_par2(dname string, loc string) partitioned by (deptno int) --指定分區列row format delimited fields terminated by ' ';--直接導入數據 指定分區列必須放到最后一列 insert into table dept_no_par2 select dname,loc,deptno from mydata.dept;--創建一張表指定分區段兩個字段 create table dept_no_par2(dname string, loc string) partitioned by (deptno int,hour int) --指定分區列row format delimited fields terminated by ' ';--直接導入數據 指定分區列必須放到最后一列 insert into table dept_no_par2 select dname,loc,deptno,hour from mydata.dept; --注意會默認分區[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gjtdpUDQ-1616598779784)(…/TypoarWrokPath/images/1616516350956.png)]
2.動態分區
--不能使用 load data inpath 'hdfs://sinlenode:8020/root/data/employee.txt' into table emp.employee_ext; 去添加數據 --將employee_hr的所有數據都插入到employee_partitioned的表中insert into table hive_demo.employee_partitioned partition(year,month) select name as name , num as num, phone as phone, shijian as shijian, year(shijian) as year ,month(shijian) as month from hive_demo.employee_hr;3.靜態分區和動態分區的區別
1.靜態分區需要手動去指定,而動態分區是基于查詢參數的位置去推斷分區的名稱
2.靜態分區的列是通過用戶在編譯時期傳遞過來的,而動態分區只有在sql執行時才能確定
28.添加分桶
1.創建分桶
create table stu_buck(id int, name string) clustered by(id) into 4 buckets --最好設置成-1 如果進行mr的時候只有兩個job任務的話那么他就值分了兩個桶 row format delimited fields terminated by ' ';--導入數據 load data local inpath '/opt/module/data/stu.txt' into table stu_buck;分桶表操作需要注意的事項
(1)reduce 的個數設置為-1,讓 Job 自行決定需要用多少個 reduce 或者將 reduce 的個
數設置為大于等于分桶表的桶數
(2)從 hdfs 中 load 數據到分桶表中,避免本地文件找不到問題
1.分桶對應于hdfs的文件
2.更高的查詢處理
3.根據"桶列" 的哈希函數將數據進行分桶
4.分桶只有動態分桶 – SET hive.enforce.bucketing = true; 設置動態分桶
5.定義分桶
CLUSTERED BY (employee_id) INTO 2 BUCKETS —分桶的列必須是要表中已有的列
分桶數最好是2的n次方
29.分桶抽樣
1.什么是分桶表
分桶是將數據集分解成更容易管理的若干部分的一個技術,是比表或分區更為細粒度的數據范圍劃分。針對某一列進行桶的組織,對列值哈希,然后除以桶的個數求余,決定將該條記錄存放到哪個桶中。
2.總結
1.隨機抽樣基于整行數據
--語法: TABLESAMPLE(BUCKET x OUT OF y) --注意:x 的值必須小于等于 y 的值,否則 --FAILED: SemanticException [Error 10061]: Numerator should not be bigger --than denominator in sample clause for table stu_buck--把數據分成32份 3表示從第三個桶往后找數據 SELECT * FROM table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON rand()) s;2.隨機抽樣基于指定列(使用分桶列更高效)
SELECT * FROM table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON id) s;3.隨機抽樣基于block suze
SELECT * FROM table_name TABLESAMPLE(10 PERCENT) s; --抽取百分之十 SELECT * FROM table_name TABLESAMPLE(1M) s;--抽取一兆 SELECT * FROM table_name TABLESAMPLE(10 rows) s; --抽取十行30.正則表達式
--解釋點 (.) 表示匹配除\n之外的其他任務字符串 --解釋加(+) 表示匹配匹配前面的子字符串一次或則多次 SELECT `^o.*` FROM offers; --^ 表示以什么開頭的 .*表示后面可以 有 或者 沒有 數據 -- (.+y) 解釋 表示在這個表達式前面一定要有其他的值 select name,regexp(name,'^J.+y.+') as match from emp.employee_partition; --正則匹配name以J卡頭,包含y的行,結果是true 、 false select name ,regexp(name,'.*ill.+') as Jy1 --必須有ill連在一起 ,regexp(name,'.*[il12345678]+.+') as Jy2 --任選一個字符有出現 ,regexp(name,'.*[i1l2345678]{3}.+') as Jy3 --任選3個字符連在一起出現 from emp.employee_partition ;select name ,regexp(name,'^J.+y.+') as Jy , regexp(work_place[0],'^T.+ron.+') as Tron --去匹配集合 from emp.employee_partition where Jy==true ;--選出包含name字段的列名,顯示這些列的數據 --注意要先執行 SET hive.support.quoted.identifiers = none; --才能使用 select `.*name.*` from emp.employee_ext; --表示除了col_name1 col_name2 col_name3 的列其他全部查出來 select `(col_name1|col_name2| col_name3)?+.+` from table;--匹配多個列名 --方法1 SET hive.support.quoted.identifiers = none; select `(.*id.*)|(.*name.*)` from customers; --方法2 SET hive.support.quoted.identifiers = none; select `.*id.*`,`.*name.*`,`.*city.*` from customers limit 5; --方法3 select `(.*(id|name|city).*)` from customers;31.虛擬列
hive 的虛擬列 主要有以下幾個參數
INPUT__FILE__NAME --進行劃分的輸入文件名
BLOCK__OFFSET__INSIDE__FILE --文中的塊內偏移量
ROW__OFFSET__INSIDE__BLOCK (默認不開啟,需設置參數)–文件的行偏移量
注意 每個 __ 都是 兩個下劃線~
1.INPUT__FILE__NAME --map任務讀入File的全路徑 select *, INPUT__FILE__NAME from categories; 2.BLOCK__OFFSET__INSIDE__FILE --如果是RCFile或者是SequenceFile塊壓縮格式文件則顯示Block file Offset,也就是當前快在文件的第一個字偏移量,如果是TextFile,顯示當前行的第一個字節在文件中的偏移量 select *, BLOCK__OFFSET__INSIDE__FILE from categories; 3.ROW__OFFSET__INSIDE__BLOCK --(默認不開啟,需設置參數) --RCFile和SequenceFile顯示row number, --textfile顯示為0 --注:若要顯示ROW__OFFSET__INSIDE__BLOCK ,必須設置set hive.exec.rowoffset=true;set hive.exec.rowoffset=true; --設置 select *, ROW__OFFSET__INSIDE__BLOCK from categories;1.INPUT____FILE__NAME 結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ReOsRzWY-1616598779786)(…/TypoarWrokPath/images/1616083346140.png)]
2.BLOCK____OFFSET_____INSIDE______FILE結果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CE2JAdrW-1616598779787)(…/TypoarWrokPath/images/1616083494422.png)]
3.ROW__OFFSET__INSIDE__BLOCK 結果
0表示是txt文件
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vZKJQgUE-1616598779788)(…/TypoarWrokPath/images/1616083989074.png)]
32.視圖
1.使用視圖的注意點
- Hive中的試圖,僅僅是一個sql語句的快捷方式
- hive中的視圖只是邏輯視圖,沒有物化視圖
- hive的視圖,不支持增刪改,只支持查詢
- hive的視圖,只有的查詢的時候,才會真正執行
2.創建視圖
create view 新建視圖名 as select * from 表名;
show views ; #只查看視圖
desc formatted|extended 視圖名 ;#查看視圖的詳細信息 formatted 查看全部信息 extended 是查看表結構
drop view 視圖名; #刪除視圖
側視圖
1.創建側視圖
SELECT *,s_birth FROM student LATERAL VIEW explode(split(s_birth,'-')) a AS s; -- LATERAL VIEW explode(split(s_birth,'-')) 返回一個數組 變成列進行輸出--outer 即使output為空也會生成結果 SELECT *,s_birthFROM student LATERAL VIEW OUTER explode(split(null,'-')) a AS s;--支持多層級 select name,wps,skill,score from employee lateral view explode(work_place) work_place_single as wps lateral view explode(skills_score) sks as skill,score;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Gz2g59n5-1616598779790)(…/TypoarWrokPath/images/1616210901091.png)]
33.JOIN筆記
1.內連接 inner join
--內連接,只有進行連接的兩個表中都存在與連接條件相匹配的數據才會被留下來 select * from score sco inner join student stu on sco.s_id=stu.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WVKQfle5-1616598779791)(…/TypoarWrokPath/images/1616206611766.png)]
2.左外連接 left join
--A left join B 是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為準的.--意思說,左表(A)的記錄將會全部表示出來(不管右邊的表中是否存在與它們匹配的行),而右表(B)只會顯示符合搜索條件的記錄,比如符合on,where中的條件。B表記錄不足的地方均為NULL. A left join B 等價B right join A --(在數據庫中成績只有七個人,但是學生有八個) select * from school.score scr left join school.student stu on scr.s_id= stu.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iLBiU3Dm-1616598779792)(…/TypoarWrokPath/images/1616208172898.png)]
3.右外連接 rigth join
--同理和left join相反,A right join B ,則顯示B表中所有的記錄,A表不足的用null填充 select * from score sco right join student stu on sco.s_id=stu.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-g3YBRrJn-1616598779793)(…/TypoarWrokPath/images/1616207431665.png)]
4. full outer join 等價 full join ,全外連接
--包含左、右兩個表的全部行,不管另外一邊的表中是否存在與它們匹配的行 在功能上,它等價于對這兩個數據集合分別進行左外連接和右外連接,然后再使用消去重復行的并操作將上述兩個結果集合并為一個結果集。select * from score sco full join student stu on sco.s_id=stu.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XGmQFb4j-1616598779793)(…/TypoarWrokPath/images/1616208476647.png)]
6. left semi join 左半開連接 ,會顯示左半邊表中記錄,前提是其記錄對于右半邊表滿足于on語句中判定條件。
--只會顯示左半邊的表 select * from score sco left semi join student stu on sco.s_id=stu.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9rVAZGyb-1616598779795)(…/TypoarWrokPath/images/1616208655887.png)]
7.自連接是自身連接,指同一個表自己與自己進行連接。這種一元連接通常用于從自反關系(也稱作遞歸關系)中抽取數據
select * from student stu inner join student stu1 on stu.s_id=stu1.s_id;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zYoUnmtj-1616598779795)(…/TypoarWrokPath/images/1616208844322.png)]
8.MAPJOIN
1. ,Hive中的Join可分為Common Join(Reduce階段完成join)和Map Join(Map階段完成join)
2.開啟join操作
set hive.auto.convert.join = true(默認值)
運行時自動將連接轉換為MAPJOIN
MAPJOIN操作不支持:
1.在UNION ALL, LATERAL VIEW, GROUP BY/JOIN/SORT
BY/CLUSTER BY/DISTRIBUTE BY等操作后面
在UNION, JOIN 以及其他 MAPJOIN之前
34.排序
-執行的先后順序
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nQXlgyAh-1616598779797)(…/TypoarWrokPath/images/1616490147382.png)]
1.order by
全局排序 desc 降序 asc 升序 效率低
注意:使用 order by 全局只有一個reduce
每個 Reduce內部排序(Sort By)
Sort By:對于大規模的數據集 order by 的效率非常低。在很多情況下,并不需要全局排
序,此時可以使用 sort by。
Sort by 為每個 reducer 產生一個排序文件。每個 Reducer 內部進行排序,對全局結果集
來說不是排序。
1**)設置 reduce 個數
<font color='cornflowerblue'>hive (default)> set mapreduce.job.reduces=3; </font>2**)查看設置** reduce 個數
<font color='cornflowerblue'>hive (default)> set mapreduce.job.reduces; </font>3**)根據部門編號降序查看員工信息**
<font color='cornflowerblue'>hive (default)> select * from emp sort by deptno desc; </font>4**)將查詢結果導入到文件中(按照部門編號降序排序)**
hive (default)> insert overwrite local directory '/opt/module/data/sortby-result' --路徑不能存在select * from emp sort by deptno desc; -會在對應的文件夾下面產生對應的文件個數分區(Distribute By)
Distribute By: 在有些情況下,我們需要控制某個特定行應該到哪個 reducer,通常是為
了進行后續的聚集操作。distribute by 子句可以做這件事。distribute by 類似 MR 中 partition
(自定義分區),進行分區,結合 sort by 使用。
對于 distribute by 進行測試,一定要分配多 reduce 進行處理,否則無法看到 distribute
by 的效果。
案例實操:
(1)先按照部門編號分區,再按照員工編號降序排序。
hive (default)> set mapreduce.job.reduces=3;
hive (default)> insert overwrite local directory
‘/opt/module/data/distribute-result’ select * from emp distribute by
deptno sort by empno desc;
注意:
distribute by 的分區規則是根據分區字段的 hash 碼與 reduce 的個數進行模除后,
余數相同的分到一個區。
Hive 要求 DISTRIBUTE BY 語句要寫在 SORT BY 語句之前。
6.4.6 Cluster By
當 distribute by 和 sorts by 字段相同時,可以使用 cluster by 方式。
cluster by 除了具有 distribute by 的功能外還兼具 sort by 的功能。但是排序只能是升序
排序,不能指定排序規則為 ASC 或者 DESC。
(1)以下兩種寫法等價
hive (default)> select * from emp cluster by deptno;
hive (default)> select * from emp distribute by deptno sort by deptno;
注意:按照部門編號分區,不一定就是固定死的數值,可以是 20 號和 30 號部門分到一
個分區里面去 有數據傾斜的現象
1.rank() over()
--成績相同的,并列名次,下一個名次空出被占用的名次 select name ,course ,score ,rank() over (partition by course order by score desc) rank from student ; --注意: 使用rank() over的時候,空值是最大的,如果排序字段為null,可能造成null字段排在最前面,影響排序結果。可以這樣:rank() over(partition by course order by score desc nulls last)來規避這個問題。[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ByiMMNHf-1616598779798)(…/TypoarWrokPath/images/1616401421823.png)]
2.dense_rank() over()
--成績相同的,并列名次,下一個名次不空出被占用的名次 select name ,course ,score ,dense_rank() over (partition by course order by score desc) rank[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Z3mno65B-1616598779801)(…/TypoarWrokPath/images/1616402138545.png)]
3.row_number over
--不管是否并列,都進行連續排名 select name ,course ,score ,row_number() over(partition by course order by score desc) from student ;[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0Yq8YRFl-1616598779802)(…/TypoarWrokPath/images/1616402688507.png)]
35.cast when 和 i f
--case when then else end 語法 --case sex when '男' then 1 else 0 end --解釋 當sex的值等于男的時候就是1 否則就是0 end 就是退出 select dept_id,sum(case sex when '男' then 1 else 0 end) nan,sum(case sex when '女' then 1 else 0 end) nv from emp_sex group by dept_id;--多條件判斷 select dept_id,sum(case sex when '男' then 1 when '男' then 1 when '男' then 1 when '男' then 1 else 0 end) nan,sum(case sex when '女' then 1 else 0 end) nv from emp_sex group by dept_id;--if判斷 跟java的意思一樣的 --if(sex='男',1,0) 解釋 如果sex的值是男的就返回一,否則就返回0 select dept_id,sum(if(sex='男',1,0)) nan,sum(if(sex='女',1,0)) nv from emp_sex group by dept_id;SQL練習
--1.創建數據庫 create database school_qe;--創建課程表 create table COURSE (`CNO` string comment '課程編號', `CNAME` string comment '課程名稱,', `TNO` string comment '教師編號' ) row format delimited fields terminated by ',' ; --導入數據 load data local inpath '/opt/data/COURSE.txt' into table course; --創建成績表 create table SCORE (`SNO` string comment '學生編號', `CNO` string comment '課程編號', `DEGREE` int comment '分數' ) row format delimited fields terminated by ',' ; load data local inpath '/opt/data/SCORE.txt' into table SCORE; --創建學生表 create table Student (`SNO` string comment '學生編號', `SNAME` string comment '學生姓名', `SSEX` string comment '學生性別', `SBIRTHDAY` string comment '出生年月', `CLASS` string comment '班級' ) row format delimited fields terminated by ',' ; load data local inpath '/opt/data/STUDENT.txt' into table Student; --創建老師表create table TEACHER (`TNO` string comment '教師編號', `TNAME` string comment '教師姓名', `TSEX` string comment '性別', `TBIRTHDAY` string comment '出生年月', `PROF` string comment '職稱', `DEPART` string comment '課程' )row format delimited fields terminated by ',' ; load data local inpath '/opt/data/TEACHER.txt' into table TEACHER; --2.練習 --1、查詢Score表中成績在60到80之間的所有記錄 select * from score where degree between 60 and 80; --2、查詢Score表中成績為85,86或88的記錄 select * from score where degree in(85,86,88); --3、以Cno升序、Degree降序查詢Score表的所有記錄。 select * from score order by cno asc,degree desc; --4、查詢Score表中的最高分的學生學號和課程號。 --1.第一種方式 使用order by 進行分組 SELECT a.sno,a.cno from ( SELECT * FROM score ORDER BY degree DESC LIMIT 1 ) a ; --第二種方式 使用 sort by 進行排序 select a.sno,a.cno from ( select * from score sort by degree desc limit 1 ) a ; --5、查詢Score表中至少有5名學生選修的并以3開頭的課程的平均分數。select cno,avg(degree) from scorewhere cno like'%3%'group by cnohaving count(cno) >=5; --6、查詢最低分大于70,最高分小于90的Sno列。 SELECT sno FROM score GROUP BY sno HAVING min(degree) >70 and max(degree)<90 --7、查詢所有學生的Sname、Cno和Degree列 SELECT stu.sname,sco.degree,sco.cno FROM score sco JOIN student stu on sco.sno = stu.sno --8、查詢“95033”班所選課程的平均分。 with s_is as (select sno from student where class ='95033')select avg(sco.degree) from score sco ,s_is ss where sco.sno in(ss.sno) ;基金sql題目
create table jijin(jijin_code string,jijin_time string,jijin_bcode string ) row format delimited fields terminated by ',' ;load data local inpath '/opt/data/jijin.txt' into table jijin;36.聚合運算
1.GROUP BY用于分組
Hive基本內置聚合函數與GROUP BY一起使用
如果沒有指定GROUP BY子句,則默認聚合整個表
除聚合函數外,所選的其他列也必須包含在GROUP BY中
GROUP BY支持使用CASE WHEN或表達式
支持按位置編號分組
set hive.groupby.orderby.position.alias=true;
Hive****聚合運算 - GROUP BY
select category, max(offervalue) from offers group by category;
– group by使用表達式
select if(category > 4000, ‘GOOD’, ‘BAD’) as newcat,max(offervalue)
from offers group by category if(category > 4000, ‘GOOD’, ‘BAD’);
解釋: 如果 category 大于4000 就是GOOD 否則就是 BAD group by 根據if 里面的判斷 大于4000 就根據GOOD進行
分組,小于4000就根據BAD 進行分組
2.Hive聚合運算 - HAVING
HAVING:對GROUP BY聚合結果的條件過濾
可以避免在GROUP BY之后使用子查詢
HAVING之后可以使用表達式,不建議
--having使用 select sex_age.age from employee group by sex_age.age having count(*) <= 1; --使用子查詢代替having 不建議使用 select a.age from ( select count(*) as cnt, sex_age.age from employee group by sex_age.age ) a where a.cnt <= 1;模擬面試:having 和 where有什么不同?
having 和where 都是進行篩選的,
但是having 是對于 分組之后的數據進行刪除, having 一定要和 group by 一起使用 但是group by 可以單獨使用
而 其他篩選就使用 where 進行篩選
37.窗口函數
1.窗口函數是一組特殊函數
掃描多個輸入行來計算每個輸出值,為每行數據生成一行結果
可以通過窗口函數來實現復雜的計算和聚合
38.函數
函數三大類型
1.UDF:一進一出
2.UDAF:多進一出
3.UDTF:一進多出
解釋:一和多指的是輸入數據的行數
1.系統內置函數
查看系統自帶的函數
show functions;顯示自帶的函數的用法
desc function upper;詳細顯示自帶的函數的用法
desc function extended upper;2.空字段賦值
函數說明
NVL:給值為 NULL 的數據賦值,它的格式是 NVL( value,default_value)。它的功能是如
果 value 為 NULL,則 NVL 函數返回 default_value 的值,否則返回 value 的值,如果兩個參數
都為 NULL ,則返回 NULL
--如果comm的這一列的值有空的就用-1來填充 select comm,nvl(comm, -1) from emp;3.小案列
1.準備數據
悟空 A 男 大海 A 男 宋宋 B 男 鳳姐 A 女 婷姐 B 女 婷婷 B 女2.需求
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2PubwnW1-1616598779803)(…/TypoarWrokPath/images/1616596401989.png)]
3.步驟
selectdept_id,sum(case sex when '男' then 1 else 0 end) male_count, --使用if進行判斷,然后進行累加sum(case sex when '女' then 1 else 0 end) female_count --使用if進行判斷,然后進行累加 from emp_sex group by dept_id; --對部門進行分組re 都是進行篩選的,
但是having 是對于 分組之后的數據進行刪除, having 一定要和 group by 一起使用 但是group by 可以單獨使用
而 其他篩選就使用 where 進行篩選
37.窗口函數
1.窗口函數是一組特殊函數
掃描多個輸入行來計算每個輸出值,為每行數據生成一行結果
可以通過窗口函數來實現復雜的計算和聚合
38.函數
函數三大類型
1.UDF:一進一出
2.UDAF:多進一出
3.UDTF:一進多出
解釋:一和多指的是輸入數據的行數
1.系統內置函數
查看系統自帶的函數
show functions;顯示自帶的函數的用法
desc function upper;詳細顯示自帶的函數的用法
desc function extended upper;2.空字段賦值
函數說明
NVL:給值為 NULL 的數據賦值,它的格式是 NVL( value,default_value)。它的功能是如
果 value 為 NULL,則 NVL 函數返回 default_value 的值,否則返回 value 的值,如果兩個參數
都為 NULL ,則返回 NULL
--如果comm的這一列的值有空的就用-1來填充 select comm,nvl(comm, -1) from emp;3.小案列
1.準備數據
悟空 A 男 大海 A 男 宋宋 B 男 鳳姐 A 女 婷姐 B 女 婷婷 B 女2.需求
[外鏈圖片轉存中…(img-2PubwnW1-1616598779803)]
3.步驟
selectdept_id,sum(case sex when '男' then 1 else 0 end) male_count, --使用if進行判斷,然后進行累加sum(case sex when '女' then 1 else 0 end) female_count --使用if進行判斷,然后進行累加 from emp_sex group by dept_id; --對部門進行分組總結
- 上一篇: 计算机主机后面辐射大,电脑的背面辐射大吗
- 下一篇: 写给深圳首期Python自动化开发周未班