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编程指南》