HiveQL(三):修改表ALTER TABLE

1 修改表

大多數的表屬性可以通過ALTER TABLE語句來進行修改。這種操作會修改元數據,但不會修改數據本身,比如修改表模式中出現的錯誤、改變分區路徑等。

1.1 表重命名

使用以下語句可將表log_messages重命名爲logmsgs:

ALTER TABLE log_messages RENAME TO logmsgs;

但是在hdfs上warehouse目錄下的該表的目錄還是log_messages,因爲只會更改元數據信息,而不會修改數據本身

1.2 增加、修改和刪除表分區

ALTER TABLE table_name ADD PARTITION…語句用於爲表(通常是外部表)增加一個新的分區,也可以增加多個分區:

ALTER TABLE logmsgs ADD IF NOT EXISTS
PARTITION (year=2019, month=5, day=1) LOCATION '/data/logmsgs/year=2019/month=5/day=1'
PARTITION (year=2019, month=5, day=2) LOCATION '/data/logmsgs/year=2019/month=5/day=2'
PARTITION (year=2019, month=5, day=3) LOCATION '/data/logmsgs/year=2019/month=5/day=3';

執行後hive會在上述對應的hdfs路徑下建立分區目錄,也可以利用上述語句爲外部表“引用”到一個分區,這裏本身沒有進行數據“裝載”,而是在元數據中指定一個指向數據的路徑。

查看該表的所有分區信息:

hive> show partitions logmsgs;
OK
year=2012/month=1/day=2
year=2012/month=1/day=3
year=2019/month=5/day=1
year=2019/month=5/day=2
year=2019/month=5/day=3

同時,我們可以修改某個分區的路徑:

ALTER TABLE logmsgs PARTITION(year=2019, month=5, day=1)
SET LOCATION 'hdfs://192.168.230.10:9000/data/logs/2019/05/01';

語句雖然執行成功,但是此時hdfs的/data下並沒有logs目錄,這再次說明hive並不關心一個分區對應的分區目錄是否存在,只是修改了元數據信息,不涉及數據本身。上述命令不會將數據從舊的路徑轉移走,也不會刪除舊的數據,只是重新指定了分區所對應的新路徑。

最後,可以通過如下語句刪除某個分區:

ALTER TABLE logmsgs DROP IF EXISTS PARTITION (year=2019, month=5, day=1);

執行成功後,其在hdfs上對應的分區目錄並沒有被刪除(因爲logmsgs是外部表)。對於管理表,即使是使用ALTER TABLE … ADD PARTITION語句增加的分區,分區內的數據也是會和元數據信息一起被刪除的。對於外部表,分區內的數據不會被刪除。

1.3 修改列信息

用戶可以對某個字段進行重命名,並修改其位置、類型或者註釋:

ALTER TABLE logmsgs
CHANGE COLUMN hms hours_minutes_seconds INT
COMMENT 'The hours, minutes, and seconds part of the timestamp'
AFTER severity;

即使字段名或者字段類型沒有改變,用戶也需要完全指定舊的字段名,並給出新的字段名及新的字段類型。關鍵字COLUMN和COMMENT子句都是可選的。上述語句中,我們將字段轉移到severity字段之後。如果想將這個字段移動到第一個位置,那麼只需要使用FIRST關鍵字替代AFTER other_column子句即可。

和通常一樣,這個命令只會修改元數據信息。如果用戶移動的是字段,那麼數據也應當和新的模式匹配或者通過其他某些方法修改數據以使其能夠和新模式匹配。

修改前:

hive> describe formatted logmsgs;
OK
# col_name            	data_type           	comment             
	 	 
hms                 	int                 	                    
severity            	string              	                    
server              	string              	                    
process_id          	int                 	                    
message             	string   

修改後:

hive> describe formatted logmsgs;
OK
# col_name            	data_type           	comment             
	 	 
severity            	string              	                    
hours_minutes_seconds	int                 	The hours, minutes, and seconds part of the timestamp
server              	string              	                    
process_id          	int                 	                    
message             	string    

1.4 增加列

用戶可以增加新的字段到已有的字段之後:

ALTER TABLE logmsgs ADD COLUMNS(
app_name STRING COMMENT 'Application name',
session_id BIGINT COMMENT 'The current session id'
);

COMMENT子句是可選的,如果新增的字段中有某個或多個字段位置是錯誤的,那麼需要使用ALTER TABLE table_name CHANGE COLUMN語句逐一將字段調整到正確的位置。

執行後查看錶結構:

hive> describe formatted logmsgs;
OK
# col_name            	data_type           	comment             
	 	 
severity            	string              	                    
hours_minutes_seconds	int                 	The hours, minutes, and seconds part of the timestamp
server              	string              	                    
process_id          	int                 	                    
message             	string              	                    
app_name            	string              	Application name    
session_id          	bigint              	The current session id
	 	 
# Partition Information	 	 
# col_name            	data_type           	comment             
	 	 
year                	int                 	                    
month               	int                 	                    
day                 	int   

這裏多說一點的是,對於爲表增加列,hive允許在原始數據文件之上定義一個模式。hive提供了SerDe抽象,其用於從輸入中提取數據。一個SerDe通常是從左到右進行解析的。其中,ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’通過指定的分隔符(這裏是’\t’)將行分解成列。SerDe通常是非常寬鬆的,如果某行的字段個數比預期的要少,那麼缺少的字段將返回null;如果某行的字段個數比預期的要多,那麼多出的字段將會被省略掉。

hive> CREATE TABLE weblogs (version LONG, url STRING)
    > PARTITION BY (hit_date int)
    > ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’;

hive> ! cat log1.txt
1 /mystuff
1 /toys

hive> LOAD DATA LOCAL INPATH 'log1.txt' INTO TABLE weblogs PARTITION (20110101);

hive> SELECT * FROM weblogs;
1 /mystuff 20110101
1 /toys 20110101

隨着時間的推移,可能會爲底層數據增加一個新字段。如下這個例子就是展示爲數據新增user_id字段的過程。需要注意的是,一些舊的原始數據文件可能不包含這個字段:

hive> ! cat log2.txt
2 /cars bob
2 /stuff terry

hive> ALTER TABLE weblogs ADD COLUMNS (user_id STRING);

hive> LOAD DATA LOCAL INPATH 'log2.txt' INTO TABLE weblogs PARTITION (20110102);

hive> SELECT * FROM weblogs;
1 /mystuff 20110101 NULL
1 /toys 20110101 NULL
2 /cars 20110102 bob 
2 /stuff 20110102 terry

需要注意的是,通過這種方式,無法在已有字段的開始或中間增加新字段。

1.5 刪除或替換列

下面這個語句移除了之前的server和process_id字段以及新增字段app_name和session_id,並重新指定了新的字段

ALTER TABLE logmsgs REPLACE COLUMNS (
hours_mins_secs int COMMENT 'hour, minute, seconds from timestamp',
severity STRING COMMENT 'The message severity',
message STRING COMMENT 'The rest of the message'
);

這個語句實際上重命名了之前的hours_minutes_seconds字段並且從之前的表定義的模式中移除了server、process_id、app_name和session_id字段。因爲是ALTER語句,所以只有表的元數據信息改變了,並且分區字段的信息不變

執行後,查看錶結構:

hive> describe formatted logmsgs;
OK
# col_name            	data_type           	comment             
	 	 
hours_mins_secs     	int                 	hour, minute, seconds from timestamp
severity            	string              	The message severity
message             	string              	The rest of the message
	 	 
# Partition Information	 	 
# col_name            	data_type           	comment             
	 	 
year                	int                 	                    
month               	int                 	                    
day                 	int 

1.6 修改表屬性

用戶可以增加附加的表屬性或者修改已經存在的屬性,但是無法刪除屬性:

ALTER TABLE logmsgs SET TBLPROPERTIES(
'notes'='The process id is no longer captured and this column is always NULL');

執行後查看錶結構:

hive> describe formatted logmsgs;
...
Table Parameters:	 	 
	EXTERNAL            	TRUE                
	last_modified_by    	root                
	last_modified_time  	1556961848          
	notes               	The process id is no longer captured and this column is always NULL
	transient_lastDdlTime	1556961848  

1.7 修改存儲屬性

下面這個語句 將一個分區的存儲格式修改成了SEQUENCE FILE,如果表是分區表,那麼需要使用PARTITION子句:

ALTER TABLE logmsgs
PARTITION(year=2012, month=1, day=2)
SET FILEFORMAT SEQUENCEFILE;

參考《hive編程指南》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章