- ADD COLUMN — 向表中添加新列。
- DROP COLUMN — 删除该列。
- RENAME COLUMN — 重命名现有列。
- CLEAR COLUMN — 重置列值。
- COMMENT COLUMN — 为列添加文本注释。
- MODIFY COLUMN — 更改列的类型、默认表达式、生存时间 (TTL) 和列设置。
- MODIFY COLUMN REMOVE — 移除列属性之一。
- MODIFY COLUMN MODIFY SETTING - 更改列设置。
- MODIFY COLUMN RESET SETTING - 重置列设置。
- MATERIALIZE COLUMN — 在缺少该列的 parts 中将该列物化。 下文将详细介绍这些操作。
ADD COLUMN
name、type、codec 和 default_expr 的新列 (参见 默认表达式 一节) 。
如果包含 IF NOT EXISTS 子句,那么即使该列已存在,查询也不会返回错误。如果指定了 AFTER name_after (另一个列的名称) ,则会将该列添加到表列列表中指定列的后面。如果要将列添加到表的开头,请使用 FIRST 子句。否则,该列会被添加到表的末尾。对于一系列操作,name_after 也可以是前一个操作中添加的列名。
添加列只会更改表结构,不会对数据执行任何操作。ALTER 之后,数据不会立即出现在磁盘上。如果从表中读取时某列的数据缺失,则会使用默认值填充 (如果存在默认表达式则执行它,否则使用零值或空字符串) 。该列会在数据分区片段合并后出现在磁盘上 (参见 MergeTree) 。
这种方式使我们能够立即完成 ALTER 查询,而不会增加旧数据的体量。
示例:
DROP COLUMN
name 的列。如果指定了 IF EXISTS 子句,那么即使该列不存在,查询也不会返回错误。
这会从文件系统中删除数据。由于删除的是整个文件,因此查询几乎会立即完成。
示例:
RENAME COLUMN
name 重命名为 new_name。如果指定了 IF EXISTS 子句,即使该列不存在,查询也不会报错。由于重命名不涉及底层数据,因此该查询几乎会立即完成。
注意:表的键表达式中指定的列 (无论是通过 ORDER BY 还是 PRIMARY KEY 指定) 都不能重命名。尝试修改这些列会产生 SQL Error [524]。
示例:
CLEAR COLUMN
IF EXISTS 子句,则当该列不存在时,查询不会报错。
示例:
COMMENT COLUMN
IF EXISTS 子句,则当该列不存在时,查询也不会返回错误。
每列只能有一条注释。如果该列已有注释,新的注释会覆盖之前的注释。
注释存储在 DESCRIBE TABLE 查询返回结果的 comment_expression 列中。
示例:
MODIFY COLUMN
name 列的以下属性:
- 类型
- 默认表达式
- 压缩编解码器
- 生存时间 (TTL)
- 列级设置
IF EXISTS 子句,则当该列不存在时,查询不会报错。
更改类型时,值会按对其应用 toType 函数后的方式进行转换。如果仅更改默认表达式,查询不会执行任何复杂操作,几乎会立即完成。
示例:
FIRST | AFTER 子句更改列的顺序,参见 ADD COLUMN 的说明,但在这种情况下必须指定列类型。
示例:
ALTER 查询具有原子性。对于 MergeTree 表,它还是无锁的。
用于修改列的 ALTER 查询会在副本间复制。相关指令会保存在 ZooKeeper 中,然后由各个副本执行。所有 ALTER 查询都会按相同顺序执行。该查询会等待其他副本上的相应操作完成。不过,对复制表中的列进行修改的查询可能会被中断,而所有操作仍会异步执行。
将 Nullable 列改为 Non-Nullable 时请务必小心。请确保该列中不含任何
NULL 值,否则读取时会出现问题。在这种情况下,可行的处理办法是终止该变更,并将该列改回 Nullable 类型。MODIFY COLUMN REMOVE
DEFAULT、ALIAS、MATERIALIZED、CODEC、COMMENT、TTL、SETTINGS。
语法:
MODIFY COLUMN MODIFY SETTING
max_compress_block_size 修改为 1MB:
MODIFY COLUMN RESET SETTING
max_compress_block_size 重置为默认值:
MATERIALIZE COLUMN
DEFAULT 或 MATERIALIZED 值表达式的列物化。使用 ALTER TABLE table_name ADD COLUMN column_name MATERIALIZED 添加物化列时,现有行中缺失的物化值不会自动补齐。添加或更新 DEFAULT 或 MATERIALIZED 表达式后,MATERIALIZE COLUMN 语句可用于重写现有列数据 (因为这类操作只会更新元数据,不会更改现有数据) 。请注意,对排序键中的列执行物化是无效操作,因为这可能会破坏排序顺序。
其实现方式为 变更。
对于具有新的或已更新 MATERIALIZED 值表达式的列,所有现有行都会被重写。
对于具有新的或已更新 DEFAULT 值表达式的列,其行为取决于 ClickHouse 版本:
- 在 ClickHouse < v24.2 中,所有现有行都会被重写。
- ClickHouse >= v24.2 会区分带有
DEFAULT值表达式的列中,某一行的值是在插入时显式指定的,还是由DEFAULT值表达式计算得出的。若该值是显式指定的,ClickHouse 会保持原样。若该值是计算得出的,ClickHouse 会将其更改为新的或已更新的MATERIALIZED值表达式。
- 如果指定了 PARTITION,则该列只会在指定的分区中被物化。
限制
ALTER 查询允许在嵌套数据结构中创建和删除单个元素 (列) ,但不支持创建或删除整个嵌套数据结构。要添加嵌套数据结构,可以添加名称类似 name.nested_name、类型为 Array(T) 的列。嵌套数据结构等价于多个数组列,这些列的名称在点号前具有相同的前缀。
对名称中带点的列进行重命名仅部分受支持。点号保留用于访问 Nested 子列,因此前缀 (父级名称) 必须保持不变。只有后缀 (子列名称) 可以更改。例如,a.b 可以重命名为 a.c,但不允许将 a.b 重命名为 b.d,因为这会更改 Nested 父级前缀。
不支持删除主键或采样键中的列 (即在 ENGINE 表达式中使用的列) 。只有在不会导致数据发生修改的情况下,才可以更改包含在主键中的列的类型 (例如,可以向 Enum 添加值,或将类型从 DateTime 更改为 UInt32) 。
如果 ALTER 查询不足以完成所需的表更改,可以创建一个新表,使用 INSERT SELECT 查询将数据复制到该表,然后使用 RENAME 查询切换表,并删除旧表。
ALTER 查询会阻塞该表上的所有读写。换句话说,如果在执行 ALTER 查询时有一个长时间运行的 SELECT 查询,ALTER 查询会等待其完成。同时,在此次 ALTER 执行期间,对同一张表发起的所有新查询也都会等待。
对于不自行存储数据的表 (例如 Merge 和 Distributed) ,ALTER 只会更改表结构,而不会更改下级表的结构。例如,对 Distributed 表执行 ALTER 时,还需要对所有远程服务器上的表执行 ALTER。