ALTER TABLE
描述
修改现有表,包括:
- 修改表名、分区名、索引名、列名
- 修改表注释
- 修改分区(增删分区和修改分区属性)
- 修改分桶方式和分桶数量
- 修改列(增删列和修改列顺序和注释)
- 创建或删除 rollup index
- 修改 bitmap index
- 修改表的属性
- 对表进行原子替换
- 手动执行 Compaction 合并表数据
- 删除主键索引
此操作需要对目标表具有ALTER权限。
语法
ALTER TABLE [<db_name>.]<tbl_name>
alter_clause1[, alter_clause2, ...]
alter_clause可以包含以下操作:重命名、注释、分区、分桶、列、汇总索引、Bitmap索引、表属性、交换和 Compaction。
- rename: 修改表名、rollup index 名、partition 名或列名(从 3.3.2 版本开始支持)。
- comment: 修改表的注释。从 3.1 版本开始支持。
- partition: 修改分区属性,删除分区,增加分区。
- bucket:修改分桶方式和分桶数量。
- column: 增加列,删除列,调整列顺序,修改列类型以及注释
- rollup index: 创建或删除 rollup index。
- bitmap index: 修改 bitmap index。
- swap: 原子替换两张表。
- compaction: 对指定表或分区手动执行 Compaction(数据版本合并)。从 3.1 版本开始支持。
- drop persistent index: 存算分离下删除主键索引。从 3.3.9 版本开始支持。
限制和使用注意事项
- 在一个ALTER TABLE语句中不能同时对分区、列和 Rollup 进行操作。
- 一个表一次只能有一个正在进行的schema change操作。不能同时在一个表上运行两个schema change命令。
- 对分桶、列和汇总索引的操作是异步操作。任务提交后会立即返回成功消息。可以运行SHOW ALTER TABLE命令检查进度,并运行CANCEL ALTER TABLE命令取消操作。
- 对重命名、注释、分区、Bitmap索引和交换的操作是同步操作,命令返回表示执行已完成。
重命名
重命名支持修改表名、汇总索引和分区名。
重命名表
ALTER TABLE <tbl_name> RENAME <new_tbl_name>
重命名汇总索引
ALTER TABLE [<db_name>.]<tbl_name>
RENAME ROLLUP <old_rollup_name> <new_rollup_name>
重命名分区
ALTER TABLE [<db_name>.]<tbl_name>
RENAME PARTITION <old_partition_name> <new_partition_name>
重命名列
从v3.3.2起,StarRocks支持重命名列。
ALTER TABLE [<db_name>.]<tbl_name>
RENAME COLUMN <old_col_name> [ TO ] <new_col_name>
- 将列从A重命名为B后,不支持添加名为A的新列。
- 基于重命名列构建的物化视图将失效。必须在具有新名称的列上重建它们。
修改表注释(从v3.1起)
语法:
ALTER TABLE [<db_name>.]<tbl_name> COMMENT = "<new table comment>";
修改分区
添加分区
您必须严格遵循相应的语法来添加 Range 分区或 List 分区。
- 不支持添加表达式分区。
- 请注意,尽管
PARTITION BY date_trunc(column)和PARTITION BY time_slice(column)的格式为表达式分区,两者都属于属于 Range 分区。因此,您可以使用以下 Range 分区的语法,为采用此类分区策 略的表添加新分区。
语法:
-
Range分区
ALTER TABLE
ADD { single_range_partition | multi_range_partitions } [distribution_desc] ["key"="value"];
single_range_partition ::=
PARTITION [IF NOT EXISTS] <partition_name> VALUES partition_key_desc
partition_key_desc ::=
{ LESS THAN { MAXVALUE | value_list }
| [ value_list , value_list ) } -- 注意,[ 表示左闭区间。
value_list ::=
( <value> [, ...] )
multi_range_partitions ::=
{ PARTITIONS START ("<start_date_value>") END ("<end_date_value>") EVERY ( INTERVAL <N> <time_unit> )
| PARTITIONS START ("<start_integer_value>") END ("<end_integer_value>") EVERY ( <granularity> ) } -- 即使START和END指定的分区列值是整数,分区列值仍需用双引号括起来。但EVERY子句中的间隔值不需要用双引号括起来。 -
List分区
ALTER TABLE
ADD PARTITION <partition_name> VALUES IN (value_list) [distribution_desc] ["key"="value"];
value_list ::=
value_item [, ...]
value_item ::=
{ <value> | ( <value> [, ...] ) }
参数:
-
分区相关参数:
- 对于Range分区,可以添加单个Range分区(
single_range_partition)或批量添加多个Range分区(multi_range_partitions)。 - 对于List分区,只能添加单个List分区。
- 对于Range分区,可以添加单个Range分区(
-
distribution_desc:可以为新分区单独设置桶的数量,但不能单独设置分桶方法。
-
"key"="value":可以为新分区设置属性。详情请参见CREATE TABLE。
示例:
-
Range分区
-
如果在创建表时指定了分区列为
event_day,例如PARTITION BY RANGE(event_day),并且在创建表后需要添加新分区,可以执行:ALTER TABLE site_access ADD PARTITION p4 VALUES LESS THAN ("2020-04-30"); -
如果在创建表时指定了分区列为
datekey,例如PARTITION BY RANGE (datekey),并且在创建表后需要批量添加多个分区,可以执行:ALTER TABLE site_access
ADD PARTITIONS START ("2021-01-05") END ("2021-01-10") EVERY (INTERVAL 1 DAY);
-
-
List分区
-
如果在创建表时指定了单个分区列,例如
PARTITION BY LIST (city),并且在创建表后需要添加新分区,可以执行:ALTER TABLE t_recharge_detail2
ADD PARTITION pCalifornia VALUES IN ("Los Angeles","San Francisco","San Diego"); -
如果在创建表时指定了多个分区列,例如
PARTITION BY LIST (dt,city),并且在创建表后需要添加新分区,可以执行:ALTER TABLE t_recharge_detail4
ADD PARTITION p202204_California VALUES IN
(
("2022-04-01", "Los Angeles"),
("2022-04-01", "San Francisco"),
("2022-04-02", "Los Angeles"),
("2022-04-02", "San Francisco")
);
-
删除分区
- 删除单个分区:
ALTER TABLE [<db_name>.]<tbl_name>
DROP PARTITION [ IF EXISTS ] <partition_name> [ FORCE ]
- 批量删除分区(从v3.4.0起支持):
ALTER TABLE [<db_name>.]<tbl_name>
DROP PARTITIONS [ IF EXISTS ] { partition_name_list | multi_range_partitions } [ FORCE ]
partition_name_list ::= ( <partition_name> [, ... ] )
multi_range_partitions ::=
{ START ("<start_date_value>") END ("<end_date_value>") EVERY ( INTERVAL <N> <time_unit> )
| START ("<start_integer_value>") END ("<end_integer_value>") EVERY ( <granularity> ) } -- 即使分区列值是整数,分区列值仍需用双引号括起来。但EVERY子句中的间隔值不需要用双引号括起 来。
multi_range_partitions的注意事项:
- 仅适用于Range分区。
- 涉及的参数与添加分区中的参数一致。
- 仅支持具有单个分区键的分区。
- 对于分区表,至少保留一个分区。
- 如果未指定FORCE,可以在指定时间内(默认为1天)使用RECOVER命令恢复已删除的分区。
- 如果指定了FORCE,分区将被直接删除,无论分区上是否有未完成的操作,并且无法恢复。因此,通常不推荐此操作。
添加临时分区
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD TEMPORARY PARTITION [IF NOT EXISTS] <partition_name>
{ single_range_partition | multi_range_partitions | list_partitions }
[DISTRIBUTED BY HASH (k1[,k2 ...]) [BUCKETS num]]
-- 有关 single_range_partition 和 multi_range_partitions 的详细信息,请参阅本页面中的“添加分区”部分。
list_partitions::=
PARTITION <partition_name> VALUES IN (value_list)
value_list ::=
value_item [, ...]
value_item ::=
{ <value> | ( <value> [, ...] ) }
使用临时分区替换当前分区
语法:
ALTER TABLE [<db_name>.]<tbl_name>
REPLACE PARTITION <partition_name>
partition_desc ["key"="value"]
WITH TEMPORARY PARTITION
partition_desc ["key"="value"]
[PROPERTIES ("key"="value", ...)]
删除临时分区
语法:
ALTER TABLE [<db_name>.]<tbl_name>
DROP TEMPORARY PARTITION <partition_name>
修改分区属性
语法
ALTER TABLE [<db_name>.]<tbl_name>
MODIFY PARTITION { <partition_name> | ( <partition1_name> [, <partition2_name> ...] ) | (*) }
SET ("key" = "value", ...);
用法
-
可以修改分区的以下属性:
- 存储介质
- storage_cooldown_ttl或storage_cooldown_time
- 副本数量
-
对于只有一个分区的表,分区名 与表名相同。如果表被划分为多个分区,可以使用
(*)来修改所有分区的属性,这样更方便。 -
执行
SHOW PARTITIONS FROM <tbl_name>查看修改后的分区属性。
修改分桶方法和桶的数量(从v3.2起)
语法:
ALTER TABLE [<db_name>.]<table_name>
[ partition_names ]
[ distribution_desc ]
partition_names ::=
(PARTITION | PARTITIONS) ( <partition_name> [, <partition_name> ...] )
distribution_desc ::=
DISTRIBUTED BY RANDOM [ BUCKETS <num> ] |
DISTRIBUTED BY HASH ( <column_name> [, <column_name> ...] ) [ BUCKETS <num> ]
示例:
例如,原始表是一个明细表,使用哈希分桶,桶的数量由StarRocks自动设置。
CREATE TABLE IF NOT EXISTS details (
event_time DATETIME NOT NULL COMMENT "事件的日期时间",
event_type INT NOT NULL COMMENT "事件类型",
user_id INT COMMENT "用户ID",
device_code INT COMMENT "设备代码",
channel INT COMMENT ""
)
DUPLICATE KEY(event_time, event_type)
PARTITION BY date_trunc('day', event_time)
DISTRIBUTED BY HASH(user_id);
-- 插入几天的数据
INSERT INTO details (event_time, event_type, user_id, device_code, channel) VALUES
-- 11月26日的数据
('2023-11-26 08:00:00', 1, 101, 12345, 2),
('2023-11-26 09:15:00', 2, 102, 54321, 3),
('2023-11-26 10:30:00', 1, 103, 98765, 1),
-- 11月27日的数据
('2023-11-27 08:30:00', 1, 104, 11111, 2),
('2023-11-27 09:45:00', 2, 105, 22222, 3),
('2023-11-27 11:00:00', 1, 106, 33333, 1),
-- 11月28日的数据
('2023-11-28 08:00:00', 1, 107, 44444, 2),
('2023-11-28 09:15:00', 2, 108, 55555, 3),
('2023-11-28 10:30:00', 1, 109, 66666, 1);
仅修改分桶方法
注意
- 修改适用于表中的所有分区,不能仅应用于特定分区。
- 虽然只需要修改分桶方法,但仍需在命令中使用
BUCKETS <num>指定桶的数量。如果未指定BUCKETS <num>,则表示桶的数量由StarRocks自动确定。
-
将分桶方法从哈希分桶修改为随机分桶,桶的数量仍由StarRocks自动设置。
ALTER TABLE details DISTRIBUTED BY RANDOM; -
将哈希分桶的键从
event_time, event_type修改为user_id, event_time。桶的数量仍由StarRocks自动设置。ALTER TABLE details DISTRIBUTED BY HASH(user_id, event_time);
仅修改桶的数量
注意
虽然只需要修改桶的数量,但仍需在命令中指定分桶方法,例如
HASH(user_id)。
-
将所有分区的桶的数量从StarRocks自动设置修改为10。
ALTER TABLE details DISTRIBUTED BY HASH(user_id) BUCKETS 10; -
将指定分区的桶的数量从StarRocks自动设置修改为15。
ALTER TABLE details PARTITIONS (p20231127, p20231128) DISTRIBUTED BY HASH(user_id) BUCKETS 15 ;注意
可以通过执行
SHOW PARTITIONS FROM <table_name>;查看分区名称。
同时修改分桶方法和桶的数量
注意
修改适用于表中的所有分区,不能仅应用于特定分区。
-
将分桶方法从哈希分桶修改为随机分桶,并将桶的数量从StarRocks自动设置修改为10。
ALTER TABLE details DISTRIBUTED BY RANDOM BUCKETS 10; -
修改哈希分桶的键,并将桶的数量从StarRocks自动设置修改为10。用于哈希分桶的键从原来的
event_time, event_type修改为user_id, event_time。桶的数量从StarRocks自动设置修改为10。ALTER TABLE details DISTRIBUTED BY HASH(user_id, event_time) BUCKETS 10;
修改列(添加/删除列,改变列的顺序或注释)
在指定索引的指定位置添加列
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD COLUMN column_name column_type [KEY | agg_type] [DEFAULT "default_value"]
[AFTER column_name|FIRST]
[TO rollup_index_name]
[PROPERTIES ("key"="value", ...)]
注意:
- 如果向聚合表中添加值列,需要指定agg_type。
- 如果向非聚合表(如明细表)中添加键列,需要指定KEY关键字。
- 不能将已经存在于基础索引中的列添加到汇总索引中。(如有需要,可以重 新创建汇总索引。)
向指定索引添加多个列
语法:
-
添加多个列
ALTER TABLE [<db_name>.]<tbl_name>
ADD COLUMN (column_name1 column_type [KEY | agg_type] DEFAULT "default_value", ...)
[TO rollup_index_name]
[PROPERTIES ("key"="value", ...)] -
添加多个列并使用AFTER指定添加列的位置
ALTER TABLE [<db_name>.]<tbl_name>
ADD COLUMN column_name1 column_type [KEY | agg_type] DEFAULT "default_value" AFTER column_name,
ADD COLUMN column_name2 column_type [KEY | agg_type] DEFAULT "default_value" AFTER column_name
[, ...]
[TO rollup_index_name]
[PROPERTIES ("key"="value", ...)]
注意:
-
如果向聚合表中添加值列,需要指定
agg_type。 -
如果向非聚合表中添加键列,需要指定KEY关键字。
-
不能将已经存在于基础索引中的列添加到汇总索引中。(如有需要,可以创建另一个汇总索引。)
添加生成列(从v3.1起)
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD COLUMN col_name data_type [NULL] AS generation_expr [COMMENT 'string']
可以添加生成列并指定其表达式。生成列可以用于预计算和存储表达式的结果,这显著加速了具有相同复杂表达式的查询。从v3.1起,StarRocks支持生成列。
从指定索引中删除列
语法:
ALTER TABLE [<db_name>.]<tbl_name>
DROP COLUMN column_name
[FROM rollup_index_name];
注意:
- 不能删除分区列。
- 如果从基础索引中删除列,并且该列包含在汇总索引中,也会被删除。
修改列类型、位置、注释和其他属性
语法:
ALTER TABLE [<db_name>.]<tbl_name>
MODIFY COLUMN <column_name>
[ column_type [ KEY | agg_type ] ] [ NULL | NOT NULL ]
[ DEFAULT "<default_value>"] [ COMMENT "<new_column_comment>" ]
[ AFTER <column_name> | FIRST ]
[ FROM rollup_index_name ]
[ PROPERTIES ("key"="value", ...) ]
注意:
-
如果修改聚合模型中的值列,需要指定agg_type。
-
如果修改非聚合模型中的键列,需要指定KEY关键字。
-
只能修改列的类型。列的其他属性保持不变。(即其他属性需要在语句中根据原属性显式写出,参见列部分的示例8)。
-
不能修改分区列。
-
目前支持以下类型的转换(精度损失由用户保证)。
- 将TINYINT/SMALLINT/INT/BIGINT转换为TINYINT/SMALLINT/INT/BIGINT/DOUBLE。
- 将TINYINT/SMALLINT/INT/BIGINT/LARGEINT/FLOAT/DOUBLE/DECIMAL转换为VARCHAR。VARCHAR支持修改最大长度。
- 将VARCHAR转换为TINYINT/SMALLINT/INT/BIGINT/LARGEINT/FLOAT/DOUBLE。
- 将VARCHAR转换为DATE(目前支持六种格式:"%Y-%m-%d", "%y-%m-%d", "%Y%m%d", "%y%m%d", "%Y/%m/%d, "%y/%m/%d")
- 将DATETIME转换为DATE(仅保留年月日信息,即
2019-12-09 21:47:05<-->2019-12-09) - 将DATE转换为DATETIME(将小时、分钟、秒设置为零,例如:
2019-12-09<-->2019-12-09 00:00:00) - 将FLOAT转换为DOUBLE
- 将INT转换为DATE(如果INT数据转换失败,原始数据保持不变)
-
不支持从NULL转换为NOT NULL。
-
您可以在单个 MODIFY COLUMN 子句中修改多个属性。但某些属性的组合不支持。
重新排序指定索引的列
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ORDER BY (column_name1, column_name2, ...)
[FROM rollup_index_name]
[PROPERTIES ("key"="value", ...)]
注意:
- 索引中的所有列必须写出。
- 值列列在键列之后。
修改排序键
从v3.0起 ,可以修改主键表的排序键。v3.3扩展了对明细表、聚合表和更新表的支持。
明细表和主键表中的排序键可以是任意排序列的组合。聚合表和更新表中的排序键必须包含所有键列,但列的顺序不需要与键列相同。
语法:
ALTER TABLE [<db_name>.]<table_name>
[ order_desc ]
order_desc ::=
ORDER BY <column_name> [, <column_name> ...]
示例:修改主键表中的排序键。
例如,原始表是一个主键表,其中排序键和主键耦合,即dt, order_id。
create table orders (
dt date NOT NULL,
order_id bigint NOT NULL,
user_id int NOT NULL,
merchant_id int NOT NULL,
good_id int NOT NULL,
good_name string NOT NULL,
price int NOT NULL,
cnt int NOT NULL,
revenue int NOT NULL,
state tinyint NOT NULL
) PRIMARY KEY (dt, order_id)
PARTITION BY date_trunc('day', dt)
DISTRIBUTED BY HASH(order_id);
将排序键与主键解耦,并将排序键修改为dt, revenue, state。
ALTER TABLE orders ORDER BY (dt, revenue, state);
修改STRUCT列以添加或删除字段
从v3.2.10和v3.3.2起,StarRocks支持修改STRUCT列以添加或删除字段,该字段可以是嵌套的或在ARRAY类型中。
语法:
-- 添加字段
ALTER TABLE [<db_name>.]<tbl_name> MODIFY COLUMN <column_name>
ADD FIELD field_path field_desc
-- 删除字段
ALTER TABLE [<db_name>.]<tbl_name> MODIFY COLUMN <column_name>
DROP FIELD field_path
field_path ::= [ { <field_name>. | [*]. } [ ... ] ]<field_name>
-- 注意,这里的`[*]`作为一个整体是一个预定义符号,表示在ARRAY字段中添加或删除STRUCT类型的字段。
-- 有关详细信息,请参见`field_path`的参数说明和示例。
field_desc ::= <field_type> [ AFTER <prior_field_name> | FIRST ]
参数:
field_path:要添加或删除的字段。这可以是一个简单的字段名,表示顶层字段,例如new_field_name,或者是表示嵌套字段的列访问路径,例如lv1_k1.lv2_k2.[*].new_field_name。[*]:当STRUCT类型嵌套在ARRAY类型中时,[*]表示ARRAY字段中的所有元素。用于在ARRAY字段下的所有STRUCT元素 中添加或删除字段。prior_field_name:新添加字段之前的字段。与AFTER关键字一起使用以指定新字段的顺序。如果使用FIRST关键字,则不需要指定此参数,表示新字段应为第一个字段。prior_field_name的维度由field_path确定(具体来说,是new_field_name之前的部分,即level1_k1.level2_k2.[*]),不需要显式指定。
field_path示例:
-
在嵌套在STRUCT列中的STRUCT字段中添加或删除子字段。
假设有一个列
fx stuct<c1 int, c2 struct <v1 int, v2 int>>。在c2下添加v3字段的语法是:ALTER TABLE tbl MODIFY COLUMN fx ADD FIELD c2.v3 INT操作后,列变为
fx stuct<c1 int, c2 struct <v1 int, v2 int, v3 int>>。 -
在嵌套在ARRAY字段中的每个STRUCT字段中添加 或删除子字段。
假设有一个列
fx struct<c1 int, c2 array<struct <v1 int, v2 int>>>。字段c2是一个ARRAY类型,其中包含一个具有两个字段v1和v2的STRUCT。向嵌套的STRUCT中添加v3字段的语法是:ALTER TABLE tbl MODIFY COLUMN fx ADD FIELD c2.[*].v3 INT操作后,列变为
fx struct<c1 int, c2 array<struct <v1 int, v2 int, v3 int>>>。
有关更多用法说明,请参见示例 - 列 -14。
- 目前,此功能仅在存算一体集群中支持。
- 表必须启用
fast_schema_evolution属性。 - 不支持在 STRUCT 类型中修改一个 MAP 子字段的 Value 类型,不管该 Value 类型是 ARRAY、STRUCT 还是 MAP。
- 新添加的字段不能有默认值或可空等属性。它们默认为可空,默认值为null。
- 使用此功能后,不允许直接降级集群到不支持此功能的版本。
修改汇总索引
创建汇总索引
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD ROLLUP rollup_name (column_name1, column_name2, ...)
[FROM from_index_name]
[PROPERTIES ("key"="value", ...)]
PROPERTIES:支持设置超时时间,默认超时时间为一天。
示例:
ALTER TABLE [<db_name>.]<tbl_name>
ADD ROLLUP r1(col1,col2) from r0;
批量创建汇总索引
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD ROLLUP [rollup_name (column_name1, column_name2, ...)
[FROM from_index_name]
[PROPERTIES ("key"="value", ...)],...];
示例:
ALTER TABLE [<db_name>.]<tbl_name>
ADD ROLLUP r1(col1,col2) from r0, r2(col3,col4) from r0;
注意:
- 如果未指定from_index_name,则默认从基础索引创建。
- 汇总表中的列必须是from_index中已存在的列。
- 在属性中,用户可以指定存储格式。详情请参见CREATE TABLE。
删除汇总索引
语法:
ALTER TABLE [<db_name>.]<tbl_name>
DROP ROLLUP rollup_name [PROPERTIES ("key"="value", ...)];
示例:
ALTER TABLE [<db_name>.]<tbl_name> DROP ROLLUP r1;
批量删除汇总索引
语法:
ALTER TABLE [<db_name>.]<tbl_name>
DROP ROLLUP [rollup_name [PROPERTIES ("key"="value", ...)],...];
示例:
ALTER TABLE [<db_name>.]<tbl_name> DROP ROLLUP r1, r2;
注意:不能删除基础索引。
修改Bitmap索引
Bitmap索引支持以下修改:
创建Bitmap索引
语法:
ALTER TABLE [<db_name>.]<tbl_name>
ADD INDEX index_name (column [, ...],) [USING BITMAP] [COMMENT 'balabala'];
注意:
1. 当前版本仅支持Bitmap索引。
2. BITMAP索引仅在单列中创建。
删除Bitmap索引
语法:
DROP INDEX index_name;