ALTER TABLE 语句用于更改现有 TCHouse-X 表的结构或属性。核心概念
逻辑操作: 在 TCHouse-X 中,
ALTER TABLE 主要是一个逻辑操作,用于更新元存储中存储的表元数据。物理影响: 大多数
ALTER TABLE 操作不会重写或移动实际的数据文件。然而,某些操作(例如更改文件格式、添加/删除列导致的数据不一致)可能需要用户自行执行相应的物理文件系统操作(如使用 INSERT OVERWRITE 重写数据文件)以确保数据兼容性。ALTER TABLE 语句更改现有 TCHouse-X 表的结构或属性。在 TCHouse-X 中,这主要是一个逻辑操作,用于更新 TCHouse-X 中存储的表元数据。大多数
ALTER TABLE 操作并不会真正重写或移动实际数据文件。执行 ALTER TABLE 操作时,通常还需要执行相应的物理文件系统操作,例如重写数据文件以包含额外字段,或将其转换为不同的文件格式。注意:
Iceberg 外表不支持 任何ALTER TABLE 操作。
修改表属性
语法
-- 1. 重命名或移动表ALTER TABLE [old_db_name.]old_table_name RENAME TO [new_db_name.]new_table_name;-- 2. 更改外部表的存储属性 (仅限外部表)ALTER TABLE nameSET { FILEFORMAT file_format| ROW FORMAT row_format| LOCATION 'table_path_of_directory' };-- 3. 设置表属性ALTER TABLE name SET TBLPROPERTIES ('key'='val', ...);
语法说明
子句 | 描述 | TCHouse-X 内表是否支持 |
RENAME TO | 更改表名,或将表移动到另一个数据库。 | 不支持 |
SET FILEFORMAT | 更改底层数据文件的格式(如 PARQUET, TEXTFILE)。 | 不支持 |
SET ROW FORMAT | 更改行数据的格式(如 DELIMITED 分隔符)。 | 不支持 |
SET LOCATION | 更改外部表数据文件所在的目录。 | 不支持 |
SET TBLPROPERTIES | 用于设置表自定义属性。 | 支持 |
修改列
ALTER TABLE 提供了多种修改表列定义的方法,主要影响元数据。语法
-- 添加新列ALTER TABLE name ADD [IF NOT EXISTS] COLUMNS (col_spec[, col_spec ...]);ALTER TABLE name ADD COLUMN [IF NOT EXISTS] col_spec;-- 替换所有现有列(注意:内部 TCHouse-X 表不支持此操作)ALTER TABLE name REPLACE COLUMNS (col_spec[, col_spec ...]);-- 修改单个列的名称、类型或注释ALTER TABLE name CHANGE column_name col_spec;-- 删除列ALTER TABLE name DROP [COLUMN] column_name;-- 修改列的注释ALTER TABLE name ALTER [COLUMN] column_name SET COMMENT 'comment_text';-- 设置列的统计信息ALTER TABLE name SET COLUMN STATS col_name('statsKey'='val', ...);-- 列规范(col_spec)的定义:-- 列名 类型名称 [COMMENT '列注释']col_spec ::= col_name type_name [COMMENT 'column-comment']-- 列统计信息键(statsKey)的定义:-- numDVs(去重值数量)| numNulls(空值数量)| avgSize(平均长度)| maxSize(最大长度)statsKey ::= numDVs | numNulls | avgSize | maxSize
注意:
TCHouse-X 内表不支持
REPLACE COLUMNS 子句。变更列类型支持情况如下:
类型分类 | 变更方向 | 结果 | 示例 |
整数类型 | 扩大存储范围 | 支持 | INT → BIGINT |
| 缩小存储范围 | 不支持 | BIGINT → INT |
浮点类型 | 增加精度 | 支持 | FLOAT → DOUBLE |
| 降低精度 | 不支持 | DOUBLE → FLOAT |
DECIMAL | 扩大精度 (p) | 支持 (需保持 s 不变) | DECIMAL(9,0) → DECIMAL(18,0) |
| 缩小精度 (p) | 不支持 | DECIMAL(18,0) → DECIMAL(9,0) |
添加列
您可以一次添加多个列。
如果使用
IF NOT EXISTS,当列已存在时 TCHouse-X 会忽略请求,不会返回错误。数据兼容性: 对于底层数据文件中不存在的新增列,所有旧数据行在该列的值都将被视为
NULL。示例
-- 准备工作:创建表并插入初始数据CREATE TABLE t1 (x int);INSERT INTO t1 VALUES (1), (2);-- 添加列 s 和 tALTER TABLE t1 ADD COLUMNS (s string, t timestamp);INSERT INTO t1 VALUES (3, 'three', '2014-11-02 01:30:00');-- 再次添加列 bALTER TABLE t1 ADD COLUMNS (b boolean);INSERT INTO t1 VALUES (4, 'four', '2014-11-02 01:03:00', true);-- 查询结果显示:旧数据在新增列上的值为 NULLSELECT * FROM t1 ORDER BY x;/*+---+-------+---------------------+------+| x | s | t | b |+---+-------+---------------------+------+| 1 | NULL | NULL | NULL || 2 | NULL | NULL | NULL || 3 | three | 2014-11-02 01:30:00 | NULL || 4 | four | 2014-11-02 01:03:00 | 1 |+---+-------+---------------------+------+*/
设置列统计信息
您可以使用不区分大小写的符号名称指定统计类型:
numDVs(不同值数量)、numNulls(空值数量)、avgSize(平均大小)、maxSize(最大大小)。键名称和值都需要用引号括起来。示例
-- 准备工作:创建表并插入初始数据CREATE TABLE t1 (x int, s string);INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (2, 'deux');-- 查看初始统计信息-- 注意:-1 通常表示尚未计算或缺失统计数据SHOW COLUMN STATS t1;/*+--------+--------+------------------+--------+----------+----------+| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |+--------+--------+------------------+--------+----------+----------+| x | INT | -1 | -1 | 4 | 4 || s | STRING | -1 | -1 | -1 | -1 |+--------+--------+------------------+--------+----------+----------+*/-- 手动设置列统计信息-- numDVs: 去重后的值数量, numNulls: 空值数量ALTER TABLE t1 SET COLUMN STATS x ('numDVs'='2','numNulls'='0');ALTER TABLE t1 SET COLUMN STATS s ('numdvs'='3','maxsize'='4');-- 检查更新后的统计信息SHOW COLUMN STATS t1;/*+--------+--------+------------------+--------+----------+----------+| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |+--------+--------+------------------+--------+----------+----------+| x | INT | 2 | 0 | 4 | 4 || s | STRING | 3 | -1 | 4 | -1 |+--------+--------+------------------+--------+----------+----------+*/
修改分区
注意:
1. 本节内容主要适用于 Hive 外部表。
2. 表必须是分区表(使用 PARTITIONED BY 子句创建)。分区是文件系统中的物理目录,其名称编码了特定的列值
语法
-- 添加分区-- 可以指定分区列及其对应的值,可选是否指定存储路径 (location_spec)ALTER TABLE name ADD [IF NOT EXISTS] PARTITION (partition_spec) [location_spec];-- 删除分区-- 使用 PURGE 关键字可以跳过回收站,直接从文件系统中物理删除数据ALTER TABLE name DROP [IF EXISTS] PARTITION (partition_spec) [PURGE];-- 修改分区属性-- 可以单独为某个分区设置文件格式、行格式或存储目录路径ALTER TABLE name PARTITION (partition_spec)SET { FILEFORMAT file_format| ROW FORMAT row_format| LOCATION 'table_path_of_directory' };-- 分区规范 (partition_spec) 的定义:-- 格式为:分区列名 = 常量值partition_spec ::= partition_col=constant_value
添加分区
TCHouse-X 的
INSERT 语句会在必要时自动创建分区,因此 ALTER TABLE ... ADD PARTITION 主要用于数据导入场景。目的: 手动在元存储中注册一个新的分区元数据,通常指向一个已经包含数据文件的文件系统目录。
数据导入方式:
使用
LOAD DATA 语句将文件移动到新创建的分区目录中。使用
ALTER TABLE ... PARTITION (...) SET LOCATION 将分区元数据指向一个已经包含数据的目录。删除分区
DROP PARTITION 子句用于删除某组分区键值对应的文件系统目录及其关联的数据文件。使用场景:
数据治理: 删除不再需要的旧分区(例如,只分析最近三个月的数据)。
性能提升: 减少与表关联的元数据量和查询计划的复杂性,从而简化并加速对分区表的执行。
使用 IF [NOT] EXISTS 确保 SQL 成功执行
为了在添加或删除分区时避免因分区已存在或不存在而抛出错误,可以使用可选的
IF [NOT] EXISTS 或 IF EXISTS 子句,以确保语句能够成功执行。示例
-- 准备工作:创建分区表并创建 1990 和 2000 分区CREATE EXTERNAL TABLE partition_t (s string) PARTITIONED BY (y int) STORED AS TEXTFILE LOCATION 'cosn://your_path';ALTER TABLE partition_t ADD PARTITION (y=1990);ALTER TABLE partition_t ADD PARTITION (y=2000);-- 尝试添加已存在的分区(将失败)ALTER TABLE partition_t ADD PARTITION (y=2000);-- ERROR: AnalysisException: Partition spec already exists: (y=2000).-- 使用 IF NOT EXISTS 成功执行(即使 2000 已存在,2010 是新创建)ALTER TABLE partition_t ADD IF NOT EXISTS PARTITION (y=2000);ALTER TABLE partition_t ADD IF NOT EXISTS PARTITION (y=2010);-- 使用 IF EXISTS 成功删除(即使 1950 不存在,2000 被删除)ALTER TABLE partition_t DROP IF EXISTS PARTITION (y=2000);ALTER TABLE partition_t DROP IF EXISTS PARTITION (y=1950);
多分区批量操作
对于
DROP 或 SET 操作,PARTITION 子句的表达式可以包含比较运算符(如 <, IN, BETWEEN)和布尔运算符(如 AND, OR),允许一次性针对多个分区执行操作。分区键值可以是常量表达式: 可以使用不引用任何列的任意常量表达式来指定分区键的值。
示例
-- 示例:使用常量表达式添加分区ALTER TABLE time_data ADD PARTITION (month=concat('Decem','ber'));-- 示例:删除过期数据ALTER TABLE historical_data DROP PARTITION (year < 1995);-- 示例:复合条件删除分区(逗号分隔等同于 AND)ALTER TABLE historical_data DROP PARTITION (year < 1995, last_name like 'A%');-- 示例:批量更改文件格式ALTER TABLE fast_growing_data PARTITION (year = 2016, month in (10,11,12))SET FILEFORMAT parquet;
说明:
对多个分区生效的 DDL 语句即使没有分区匹配条件也视为成功(不产生任何更改),其结果等同于指定了
IF EXISTS 子句。此方法的性能类似于快速连续执行一系列单分区
ALTER TABLE 语句。自动检测新分区目录
注意:
1. 本节内容主要适用于 Hive 外部表。
2. 表必须是分区表(使用 PARTITIONED BY 子句创建)。分区是文件系统中的物理目录,其名称编码了特定的列值
当新的分区目录在 TCHouse-X 外部被创建和添加数据(例如通过 Hive
ALTER TABLE 语句或直接的 HDFS/COS 命令操作)时,RECOVER PARTITIONS 子句会扫描表的数据目录,自动检测这些新添加的分区目录及其中的数据文件,并将相应的元数据注册到 TCHouse-X。语法
ALTER TABLE name RECOVER PARTITIONS
示例
-- 准备工作(创建外部表并创建一个分区)CREATE EXTERNAL TABLE t1 (s string) PARTITIONED BY (year int, month int) STORED AS TEXTFILE LOCATION 'cosn://path';ALTER TABLE t1 ADD PARTITION (year = 2016, month = 1);-- t1 看到一个分区SHOW PARTITIONS t1-- 删除分区ALTER TABLE t1 DROP PARTITION (year = 2016, month = 1);-- t1 下没有分区SHOW PARTITIONS t1-- 执行 RECOVER PARTITIONS 扫描 COS 目录并注册新的分区元数据ALTER TABLE t1 RECOVER PARTITIONS;-- t1 看到一个分区SHOW PARTITIONS t1
SYNC DATA
注意:
该操作仅 TCHouse-X 内表支持。
ALTER TABLE name EXECUTE SYNC_DATA();
TCHouse-X 内表在数据写入后,会先写 WAL 日志,WAL日志持久化成功后,会立即返回成功。TCHouse-X 存储引擎后台会把 WAL 日志转换成内表存储格式。在 WAL 转成内表存储格式之前,这次写入的数据是无法查询的。
可以使用 SYNC DATA 语句强制存储引擎把 WAL 日志数据转换成内表存储格式,这样就可以查询到新写入的数据。
目前 SYNC DATA 默认超时是60s,如果一次写入的数据非常多,可能会出现超时的情况,重试即可。