alter
ALTER
ALTER
仅支持 *MergeTree
,Merge
以及Distributed
等引擎表。
该操作有多种形式。
列操作
改变表结构:
ALTER TABLE [db].name [ON CLUSTER cluster] ADD|DROP|CLEAR|COMMENT|MODIFY COLUMN ...
在语句中,配置一个或多个用逗号分隔的动作。每个动作是对某个列实施的操作行为。
支持下列动作:
- ADD COLUMN — 添加列
- DROP COLUMN — 删除列
- CLEAR COLUMN — 重置列的值
- COMMENT COLUMN — 给列增加注释说明
- MODIFY COLUMN — 改变列的值类型,默认表达式以及TTL
这些动作将在下文中进行详述。
增加列
ADD COLUMN [IF NOT EXISTS] name [type] [default_expr] [codec] [AFTER name_after]
使用指定的name
, type
, codec
以及 default_expr
(请参见 Default expressions),往表中增加新的列。
如果sql中包含 IF NOT EXISTS
,执行语句时如果列已经存在,CH不会报错。如果指定AFTER name_after
(表中另一个列的名称),则新的列会加在指定列的后面。否则,新的列将被添加到表的末尾。注意,不能将新的列添加到表的开始位置, name_after
可以是执行该动作时已经在表中存在的任意列。
添加列仅仅是改变原有表的结构不会对已有数据产生影响。执行完 ALTER
后磁盘中也不会出现新的数据。如果查询表时列的数据为空,那么CH会使用列的默认值来进行填充(如果有默认表达式,则使用这个;或者用0或空字符串)。当数据块完成合并(参见MergeTree)后,磁盘中会出现该列的数据。
这种方式允许 ALTER
语句能马上执行。不需要增加原有数据的大小。
示例:
ALTER TABLE visits ADD COLUMN browser String AFTER user_id
删除列
DROP COLUMN [IF EXISTS] name
通过指定 name
删除列。如果语句包含 IF EXISTS
,执行时遇到不存在的列也不会报错。
从文件系统中删除数据。由于是删除列的整个文件,该语句几乎是立即执行完成的。
示例:
ALTER TABLE visits DROP COLUMN browser
清空列
CLEAR COLUMN [IF EXISTS] name IN PARTITION partition_name
重置指定分区中列的值。 分区名称 partition_name
请参见 怎样设置分区表达式
如果语句中包含 IF EXISTS
,遇到不存在的列,sql执行不会报错。
示例:
ALTER TABLE visits CLEAR COLUMN browser IN PARTITION tuple()
增加注释
COMMENT COLUMN [IF EXISTS] name 'comment'
给列增加注释说明。如果语句中包含 IF EXISTS
,遇到不存在的列,sql执行不会报错。
每个列都可以包含注释。如果列的注释已经存在,新的注释会替换旧的。
注释信息保存在 DESCRIBE TABLE查询的 comment_expression
字段中。
示例:
ALTER TABLE visits COMMENT COLUMN browser 'The table shows the browser used for accessing the site.'
修改列
MODIFY COLUMN [IF EXISTS] name [type] [default_expr] [TTL]
该语句可以改变 name
列的属性:
-
Type
-
Default expression
-
TTL
有关修改列TTL的示例,请参见 Column TTL.
如果语句中包含 IF EXISTS
,遇到不存在的列,sql执行不会报错。
当改变列的类型时,列的值也被转换了,如同对列使用 toType函数一样。如果只改变了默认表达式,该语句几乎不会做任何复杂操作,并且几乎是立即执行完成的。
示例:
ALTER TABLE visits MODIFY COLUMN browser Array(String)
改变列的类型是唯一的复杂型动作 - 它改变了数据文件的内容。对于大型表,执行起来要花费较长的时间。 该操作分为如下处理步骤:
- 为修改的数据准备新的临时文件
- 重命名原来的文件
- 将新的临时文件改名为原来的数据文件名
- 删除原来的文件
仅仅在第一步是耗费时间的。如果该阶段执行失败,那么数据没有变化。如果执行后续的步骤中失败了,数据可以手动恢复。例外的情形是,当原来的文件从文件系统中被删除了,但是新的数据没有写入到临时文件中并且丢失了。
列操作的 ALTER
行为是可以被复制的。这些指令会保存在ZooKeeper中,这样每个副本节点都能执行它们。所有的 ALTER
将按相同的顺序执行。
The query waits for the appropriate actions to be completed on the other replicas.
然而,改变可复制表的列是可以被中断的,并且所有动作都以异步方式执行。
ALTER 操作限制
ALTER
操作允许在嵌套的数据结构中创建和删除单独的元素(列),但是不是整个嵌套结构。添加一个嵌套数据结构的列时,你可以用类似这样的名称 name.nested_name
及类型 Array(T)
来操作。嵌套数据结构等同于
列名前带有同样前缀的多个数组列。
不支持对primary key或者sampling key中的列(在 ENGINE
表达式中用到的列)进行删除操作。改变包含在primary key中的列的类型时,如果操作不会导致数据的变化(例如,往Enum中添加一个值,或者将DateTime
类型改成 UInt32
),那么这种操作是可行的。
如果 ALTER
操作不足以完成你想要的表变动操作,你可以创建一张新的表,通过 INSERT SELECT将数据拷贝进去,然后通过 RENAME将新的表改成和原有表一样的名称,并删除原有的表。
ALTER
操作会阻塞对表的所有读写操作。换句话说,当一个大的 SELECT
语句和 ALTER
同时执行时,ALTER
会等待,直到 SELECT
执行结束。与此同时,当 ALTER
运行时,新的 sql 语句将会等待。
对于不存储数据的表(例如 Merge
及 Distributed
表), ALTER
仅仅改变了自身的表结构,不会改变从属的表结构。例如,对 Distributed
表执行 ALTER 操作时,需要对其它包含该表的服务器执行该操作。
key表达式的修改
支持下列表达式:
MODIFY ORDER BY new_expression
该操作仅支持 MergeTree
系列表 (含 replicated 表)。它会将表的 排序键变成 new_expression
(元组表达式)。主键仍保持不变。
该操作是轻量级的,仅会改变元数据。
跳过索引来更改数据
该操作仅支持 MergeTree
系列表 (含 replicated 表)。
下列操作是允许的:
-
ALTER TABLE [db].name ADD INDEX name expression TYPE type GRANULARITY value [FIRST|AFTER name]
- 在表的元数据中增加索引说明 -
ALTER TABLE [db].name DROP INDEX name
- 从表的元数据中删除索引描述,并从磁盘上删除索引文件
由于只改变表的元数据或者删除文件,因此该操作是轻量级的,也可以被复制到其它节点(通过Zookeeper同步索引元数据)
更改约束
参见 constraints查看更多信息。
通过下面的语法,可以添加或删除约束:
ALTER TABLE [db].name ADD CONSTRAINT constraint_name CHECK expression;
ALTER TABLE [db].name DROP CONSTRAINT constraint_name;
上述语句会从表中增加或删除约束的元数据,因此会被立即处理。 对已有数据的约束检查 将不会执行 。
对可复制表的操作可通过Zookeeper传播到其它副本节点。
更改分区及文件块
允许进行下列关于 partitions 的操作:
- DETACH PARTITION — 将分区数据移动到
detached
,并且忘记它 - DROP PARTITION — 删除一个partition.
- ATTACH PART|PARTITION — 将
detached
目录中的分区重新添加到表中. - ATTACH PARTITION FROM — 从表中复制数据分区到另一张表,并添加分区
- REPLACE PARTITION — 从表中复制数据分区到其它表及副本
- MOVE PARTITION TO TABLE — 从表中复制数据分区到其它表.
- CLEAR COLUMN IN PARTITION — 重置分区中某个列的值
- CLEAR INDEX IN PARTITION — 重置分区中指定的二级索引
- FREEZE PARTITION — 创建分区的备份
- FETCH PARTITION — 从其它服务器上下载分
- MOVE PARTITION|PART — 将分区/数据块移动到另外的磁盘/卷
分区剥离
ALTER TABLE table_name DETACH PARTITION partition_expr
将指定分区的数据移动到 detached
目录。服务器会忽略被分离的数据分区。只有当你使用 ATTACH 时,服务器才会知晓这部分数据。
示例:
ALTER TABLE visits DETACH PARTITION 201901
从 如何设置分区表达式章节中获取分区表达式的设置说明。
当执行操作以后,可以对 detached
目录的数据进行任意操作,例如删除文件,或者放着不管。
该操作是可以复制的,它会将所有副本节点上的数据移动到 detached
目录。注意仅能在副本的leader节点上执行该操作。想了解副本是否是leader节点,需要在 system.replicas 表执行 SELECT
操作。或者,可以很方便的在所有副本节点上执行 DETACH
操作,但除leader外其它的副本节点会抛出异常。
删除分区
ALTER TABLE table_name DROP PARTITION partition_expr
从表中删除指定分区。该操作会将分区标记为不活跃的,然后在大约10分钟内删除全部数据。
在 如何设置分区表达式中获取分区表达式的设置说 明。 该操作是可复制的,副本节点的数据也将被删除。
删除已剥离的分区|数据块
ALTER TABLE table_name DROP DETACHED PARTITION|PART partition_expr
从detached
目录中删除指定分区的特定部分或所有数据。访问 如何设置分区表达式可获取设置分区表达式的详细信息。
关联分区|数据块
ALTER TABLE table_name ATTACH PARTITION|PART partition_expr
从detached
目录中添加数据到数据表。可以添加整个分区的数据,或者单独的数据块。例如:
ALTER TABLE visits ATTACH PARTITION 201901;
ALTER TABLE visits ATTACH PART 201901_2_2_0;
访问 如何设置分区表达式可获取设置分区表达式的详细信息。
该操作是可以复制的。副本启动器检查 detached
目录是否有数据。如果有,该操作会检查数据的完整性。如果一切正常,该操作将数据添加到表中。其它副本节点通过副本启动器下载这些数据。
因此可以在某个副本上将数据放到 detached