大數(shù)據(jù)離線階段 06:HQL數(shù)據(jù)定義語言(DDL)概述
HQL數(shù)據(jù)定義語言(DDL)概述
DDL語法的作用
數(shù)據(jù)定義語言 (Data Definition Language, DDL),是SQL語言集中對數(shù)據(jù)庫內(nèi)部的對象結(jié)構(gòu)進行創(chuàng)建,刪除,修改等的操作語言,這些數(shù)據(jù)庫對象包括database(schema)、table、view、index等。核心語法由CREATE、ALTER與DROP三個所組成。DDL并不涉及表內(nèi)部數(shù)據(jù)的操作。
在某些上下文中,該術(shù)語也稱為數(shù)據(jù)描述語言,因為它描述了數(shù)據(jù)庫表中的字段和記錄。

Hive中DDL使用
Hive SQL(HQL)與SQL的語法大同小異,基本上是相通的,學(xué)過SQL的使用者可以無痛使用Hive SQL。只不過在學(xué)習(xí)HQL語法的時候,特別要注意Hive自己特有的語法知識點,比如partition相關(guān)的DDL操作。
基于Hive的設(shè)計、使用特點,HQL中create語法(尤其create table)將是學(xué)習(xí)掌握DDL語法的重中之重??梢哉f建表是否成功直接影響數(shù)據(jù)文件是否映射成功,進而影響后續(xù)是否可以基于SQL分析數(shù)據(jù)。通俗點說,沒有表,表沒有數(shù)據(jù),你分析什么呢?
選擇正確的方向,往往比盲目努力重要。
Hive DDL建表基礎(chǔ)
完整建表語法樹

藍色字體是建表語法的關(guān)鍵字,用于指定某些功能。
[]中括號的語法表示可選。
|表示使用的時候,左右語法二選一。
建表語句中的語法順序要和上述語法規(guī)則保持一致。
Hive數(shù)據(jù)類型詳解
整體概述
Hive中的數(shù)據(jù)類型指的是Hive表中的列字段類型。Hive數(shù)據(jù)類型整體分為兩個類別:原生數(shù)據(jù)類型(primitive data type)和復(fù)雜數(shù)據(jù)類型(complex data type)。
原生數(shù)據(jù)類型包括:數(shù)值類型、時間類型、字符串類型、雜項數(shù)據(jù)類型;
復(fù)雜數(shù)據(jù)類型包括:array數(shù)組、map映射、struct結(jié)構(gòu)、union聯(lián)合體。

關(guān)于Hive的數(shù)據(jù)類型,需要注意:
英文字母大小寫不敏感;
除SQL數(shù)據(jù)類型外,還支持Java數(shù)據(jù)類型,比如:string;
int和string是使用最多的,大多數(shù)函數(shù)都支持;
復(fù)雜數(shù)據(jù)類型的使用通常需要和分隔符指定語法配合使用。
如果定義的數(shù)據(jù)類型和文件不一致,hive會嘗試隱式轉(zhuǎn)換,但是不保證成功。
原生數(shù)據(jù)類型
Hive支持的原生數(shù)據(jù)類型如下圖所示:

其中標(biāo)注的數(shù)據(jù)類型是使用較多的,詳細(xì)的描述請查詢語法手冊:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
復(fù)雜數(shù)據(jù)類型
Hive支持的復(fù)雜數(shù)據(jù)類型如下圖所示:

其中標(biāo)注的數(shù)據(jù)類型是使用較多的,詳細(xì)的描述請查詢語法手冊:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
數(shù)據(jù)類型隱式、顯示轉(zhuǎn)換
與SQL類似,HQL支持隱式和顯式類型轉(zhuǎn)換。
原生類型從窄類型到寬類型的轉(zhuǎn)換稱為隱式轉(zhuǎn)換,反之,則不允許。
下表描述了類型之間允許的隱式轉(zhuǎn)換:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
顯式類型轉(zhuǎn)換使用CAST函數(shù)。
例如,CAST('100'as INT)會將100字符串轉(zhuǎn)換為100整數(shù)值。 如果強制轉(zhuǎn)換失敗,例如CAST('INT'as INT),該函數(shù)返回NULL。

Hive讀寫文件機制
SerDe是什么
SerDe是Serializer、Deserializer的簡稱,目的是用于序列化和反序列化。序列化是對象轉(zhuǎn)化為字節(jié)碼的過程;而反序列化是字節(jié)碼轉(zhuǎn)換為對象的過程。
Hive使用SerDe(和FileFormat)讀取和寫入行對象。

需要注意的是,“key”部分在讀取時會被忽略,而在寫入時key始終是常數(shù)。基本上行對象存儲在“value”中。
可以通過desc formatted tablename查看表的相關(guān)SerDe信息。默認(rèn)如下:

Hive讀寫文件流程
Hive讀取文件機制:首先調(diào)用InputFormat(默認(rèn)TextInputFormat),返回一條一條kv鍵值對記錄(默認(rèn)是一行對應(yīng)一條記錄)。然后調(diào)用SerDe(默認(rèn)LazySimpleSerDe)的Deserializer,將一條記錄中的value根據(jù)分隔符切分為各個字段。
Hive寫文件機制:將Row寫入文件時,首先調(diào)用SerDe(默認(rèn)LazySimpleSerDe)的Serializer將對象轉(zhuǎn)換成字節(jié)序列,然后調(diào)用OutputFormat將數(shù)據(jù)寫入HDFS文件中。
SerDe相關(guān)語法
在Hive的建表語句中,和SerDe相關(guān)的語法為:
其中ROW FORMAT是語法關(guān)鍵字,DELIMITED和SERDE二選其一。
如果使用delimited表示使用默認(rèn)的LazySimpleSerDe類來處理數(shù)據(jù)。如果數(shù)據(jù)文件格式比較特殊可以使用ROW FORMAT SERDE serde_name指定其他的Serde類來處理數(shù)據(jù),甚至支持用戶自定義SerDe類。
LazySimpleSerDe分隔符指定
LazySimpleSerDe是Hive默認(rèn)的序列化類,包含4種子語法,分別用于指定字段之間、集合元素之間、map映射 kv之間、換行的分隔符號。在建表的時候可以根據(jù)數(shù)據(jù)的特點靈活搭配使用。

默認(rèn)分隔符
hive建表時如果沒有row format語法。此時字段之間默認(rèn)的分割符是'\001',是一種特殊的字符,使用的是ascii編碼的值,鍵盤是打不出來的。

在vim編輯器中,連續(xù)按下Ctrl+v/Ctrl+a即可輸入'\001' ,顯示^A

在一些文本編輯器中將以SOH的形式顯示:

Hive數(shù)據(jù)存儲路徑
默認(rèn)存儲路徑
Hive表默認(rèn)存儲路徑是由${HIVE_HOME}/conf/hive-site.xml配置文件的hive.metastore.warehouse.dir屬性指定。默認(rèn)值是:/user/hive/warehouse。

在該路徑下,文件將根據(jù)所屬的庫、表,有規(guī)律的存儲在對應(yīng)的文件夾下。

指定存儲路徑
在Hive建表的時候,可以通過location語法來更改數(shù)據(jù)在HDFS上的存儲路徑,使得建表加載數(shù)據(jù)更加靈活方便。
語法:LOCATION '<hdfs_location>'。
對于已經(jīng)生成好的數(shù)據(jù)文件,使用location指定路徑將會很方便。
案例—王者榮耀
原生數(shù)據(jù)類型案例
文件archer.txt中記錄了手游《王者榮耀》射手的相關(guān)信息,內(nèi)容如下所示,其中字段之間分隔符為制表符\t,要求在Hive中建表映射成功該文件。
字段含義:id、name(英雄名稱)、hp_max(最大生命)、mp_max(最大法力)、attack_max(最高物攻)、defense_max(最大物防)、attack_range(攻擊范圍)、role_main(主要定位)、role_assist(次要定位)。
分析一下:字段都是基本類型,字段的順序需要注意一下。字段之間的分隔符是制表符,需要使用row format語法進行指定。
建表語句:
建表成功之后,在Hive的默認(rèn)存儲路徑下就生成了表對應(yīng)的文件夾,把archer.txt文件上傳到對應(yīng)的表文件夾下。
執(zhí)行查詢操作,可以看出數(shù)據(jù)已經(jīng)映射成功。

想一想:Hive這種能力是不是比mysql一條一條insert插入數(shù)據(jù)方便多了?
復(fù)雜數(shù)據(jù)類型案例
文件hot_hero_skin_price.txt中記錄了手游《王者榮耀》熱門英雄的相關(guān)皮膚價格信息,內(nèi)容如下,要求在Hive中建表映射成功該文件。
字段:id、name(英雄名稱)、win_rate(勝率)、skin_price(皮膚及價格)
分析一下:前3個字段原生數(shù)據(jù)類型、最后一個字段復(fù)雜類型map。需要指定字段之間分隔符、集合元素之間分隔符、map kv之間分隔符。
建表語句:
建表成功后,把hot_hero_skin_price.txt文件上傳到對應(yīng)的表文件夾下。
執(zhí)行查詢操作,可以看出數(shù)據(jù)已經(jīng)映射成功。

想一想:如果最后一個字段以String類型來定義,后續(xù)使用方便嗎?
默認(rèn)分隔符案例
文件team_ace_player.txt中記錄了手游《王者榮耀》主要戰(zhàn)隊內(nèi)最受歡迎的王牌選手信息,內(nèi)容如下,要求在Hive中建表映射成功該文件。

字段:id、team_name(戰(zhàn)隊名稱)、ace_player_name(王牌選手名字)
分析一下:數(shù)據(jù)都是原生數(shù)據(jù)類型,且字段之間分隔符是\001,因此在建表的時候可以省去row format語句,因為hive默認(rèn)的分隔符就是\001。
建表語句:
建表成功后,把team_ace_player.txt文件上傳到對應(yīng)的表文件夾下。
執(zhí)行查詢操作,可以看出數(shù)據(jù)已經(jīng)映射成功。

想一想:字段以\001分隔建表時很方便,那么采集、清洗數(shù)據(jù)時對數(shù)據(jù)格式追求有什么啟發(fā)?你青睞于什么分隔符?