Hive進階篇(三)創建表+表結構*(字段類型、文件格式、行格式、分區表)
一、創建表
外部表的徹底刪除參考:https://www.cnblogs.com/liuxinrong/articles/14409076.html
二、字段類型
1、簡單的
2、復雜的
三、文件格式
1、文本
log(日志文件)、csv文件(逗號分隔的)、tsv(tab分隔的)
2、JSON(一行是一個JSON)
3、Binary(二進制格式的)效率較高
行式的(SequenceFile-用的很少了)、
列式的(使用最廣泛,Parquet(用的更多)、ORC)
PARQUET舉例--將TXT表轉換為PARQUET表:
(1)先建表結構
DROP TABLE IF EXISTS pq_access_logs; CREATE TABLE pq_access_logs ( ip STRING, request_time STRING, method STRING, url STRING, http_version STRING, code1 STRING, code2 STRING, dash STRING, user_agent STRING, `timestamp` int) STORED AS PARQUET;
(2)再將TXT表中的數據加載到建好的表中
INSERT OVERWRITE TABLE pq_access_logs SELECT ip, from_unixtime(unix_timestamp(request_time, 'dd/MMM/yyyy:HH:mm:ss z'), 'yyyy-MM-dd HH:mm:ss z'), method, url, http_version, code1, code2, dash, user_agent, unix_timestamp(request_time, 'dd/MMM/yyyy:HH:mm:ss z') FROM original_access_logs;
這里使用 from_unixtime 和 unix_timestamp函數將日/月/年的順序進行調整 變成年-月-日的形式。
Parquet-二進制存儲的查詢效率更高
三、行格式(Row Format)
1、標准分隔符
DELIMETED-反序列化(前面有DE表反)
2、需要自定義序列化類來處理
SERDE-序列化
四、分區表
1、按照日期進行分區
CREATE TABLE partitioned_access_log ( ip STRING,
) ...
PARTITIONED BY (request_date STRING) ...;
hdfs:///access_logs/ ...
— 2017_01_20
— 2017_01_21
— 2017_01_22 ...
— "today"
2、.../年/月/日 式的分區
CREATE TABLE partitioned_access_log ( ip STRING,
) ...
PARTITIONED BY (year STRING, month STRING, day STRING) ...;
hdfs:///access_logs/ ...
— 2017
—— 01
——— 20
——— 21
——— 22 ...
3、分區表的作用
避免全表掃描
提升查詢性能 減少IO
方便數據按分區寫入(覆蓋)
方便管理
4、分區表的操作演示
1)創建分區表-PARTITIONED BY
DROP TABLE IF EXISTS partitioned_access_logs; CREATE EXTERNAL TABLE partitioned_access_logs ( ip STRING, request_time STRING, method STRING, url STRING, http_version STRING, code1 STRING, code2 STRING, dash STRING, user_agent STRING, `timestamp` int) PARTITIONED BY (request_date STRING) STORED AS PARQUET ;
STORED AS PARQUET --文件格式是列式的。
2)將日志表寫入分區表,使用動態分區插入
set hive.exec.dynamic.partition.mode=nonstrict; INSERT OVERWRITE TABLE partitioned_access_logs PARTITION (request_date) SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date FROM pq_access_logs ;
解釋:
set hive.exec.dynamic.partition.mode=nonstrict; 是在設置環境變量,
nonstrict是將分區設置成不嚴格的(默認是嚴格的-strict),這樣就能開啟動態分區的插入模式了。
to_date(request_time)是將 年月日時分秒 轉換成 日期的格式了。
如果是靜態的話,可以看下面這個例子:
set hive.exec.dynamic.partition.mode=nonstrict; INSERT OVERWRITE TABLE partitioned_access_logs PARTITION (request_date = '2020-08-10') SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date FROM pq_access_logs where request_time >= '2020-08-10' and requset_time < '2020-08-11' ;
將2020年8月10號-2020年8月11號之間的數據全部插入到2020-08-10的分區中。
當然因為一年有365天左右,這樣靜態的話就得寫好多遍這段demo了,所以還是采用動態的更高效。
當然,動態分區和靜態分區也是可以混用的-混合分區:
set hive.exec.dynamic.partition.mode=nonstrict; INSERT OVERWRITE TABLE partitioned_access_logs PARTITION (year = '2020', month = '06', day) SELECT ip, request_time, method, url, http_version, code1, code2, dash, user_agent, `timestamp`, to_date(request_time) as request_date FROM pq_access_logs ;
3)查看分區表的分區情況
- show partitions + 分區表表名
(直接通過元數據進行查詢,效率最高。有的時候分區多的話,結果的時間會是無序的了)
- 還有一種是select distinct + 分區根據的屬性名 + from + 分區表表名
(需要從HDFS將文件讀一遍才可得到結果,較慢)
0: jdbc:hive2://localhost:10000> show partitions partitioned_access_logs;
結果:
+--------------------------+--+
| partition |
+--------------------------+--+
| request_date=2014-06-14 |
| request_date=2014-06-15 |
+--------------------------+--+
2 rows selected (0.277 seconds)
有兩個分區創建出來了-兩天的日志信息
4)看分區表的目錄形式
[root@cdh alternatives]# hdfs dfs -ls /user/hive/warehouse/partitioned_access_logs/
Found 2 items
drwxrwxrwt - hive hive 0 2021-02-17 14:55 /user/hive/warehouse/partitioned_access_logs/request_date=2014-06-14
drwxrwxrwt - hive hive 0 2021-02-17 14:55 /user/hive/warehouse/partitioned_access_logs/request_date=2014-06-15
可以看到該分區表的各分區之間是並列的形式
Hive的分區目錄名結尾是一種key(分區字段)=value(日期)的形式,不僅僅只有日期
每個分區目錄下面存的就是分區內的結果文件,文件的命名會以編號的形式按順序拍好.
5) 分區表加字段
alter table + 分區表名 + add columns (要增加的分區字段名 + 數據類型);
下面的寫法也可以:
alter table + 分區表名(也可以是數據庫.表名的形式) + add + partition (分區字段名 = '指定的分區名中的日期')
注:分區表新加入的字段並不能真正插入數據,
因為老的分區結構是在表結構剛建好之后就保存在元數據中的,是不會因為新字段的加入就改變的.
如果要增加分區並且真正地可以插入數據的話,
- 對於內部表:就需要刪除分區表,然后再創建一個新的分區表. 因為刪除個別分區之后里面的數據也會被刪除.
- 對於外部表:可先刪除掉新加的分區字段所在的分區(刪掉的僅僅是表結構),再將其重建即可顯示出來了.
6) 讀取個別分區
select * from + 分區表的表名+ where + 分區字段名 = '指定的分區名中的日期'
也可以在后面加上 limit+行數 進行打印行數的限制
7) 刪除個別分區字段
alter table + 分區表名(也可以是數據庫.表名的形式) + drop + partition (分區字段名 = '指定的分區名中的日期')
五、Storage Handler
通過創建一個外部表 Create External Table to Export Data
將數據導入到不同的數據庫中 像:
1.HBase
2.ElasticSearch