修改表 #

一、ALTER TABLE概述 #

1.1 可修改内容 #

ALTER TABLE支持以下修改:

操作 支持 说明
添加列 添加新列
删除列 删除现有列
修改列类型 仅限兼容类型
修改表属性 压缩、缓存等
修改主键 不支持
修改表名 不支持

1.2 基本语法 #

sql
-- 添加列
ALTER TABLE table_name ADD (column_name data_type, ...);

-- 删除列
ALTER TABLE table_name DROP column_name;

-- 修改列类型
ALTER TABLE table_name ALTER column_name TYPE new_data_type;

-- 修改表属性
ALTER TABLE table_name WITH option_name = option_value;

二、添加列 #

2.1 添加单列 #

sql
-- 添加单个列
ALTER TABLE users ADD phone TEXT;

-- 添加多个列
ALTER TABLE users ADD (
    phone TEXT,
    address TEXT,
    city TEXT
);

2.2 添加集合类型列 #

sql
-- 添加List列
ALTER TABLE users ADD tags LIST<TEXT>;

-- 添加Set列
ALTER TABLE users ADD email_list SET<TEXT>;

-- 添加Map列
ALTER TABLE users ADD preferences MAP<TEXT, TEXT>;

2.3 添加UDT列 #

sql
-- 先创建UDT
CREATE TYPE address (
    street TEXT,
    city TEXT,
    state TEXT,
    zip_code TEXT
);

-- 添加UDT列
ALTER TABLE users ADD home_address FROZEN<address>;

2.4 添加列注意事项 #

text
添加列注意事项:

✓ 可以添加任意数量的列
✓ 新列默认值为NULL
✓ 不影响现有数据
✓ 添加后立即可用

✗ 不能添加主键列
✗ 不能添加与现有列同名的列

三、删除列 #

3.1 删除单列 #

sql
-- 删除单个列
ALTER TABLE users DROP phone;

-- 删除多个列(需要分别执行)
ALTER TABLE users DROP address;
ALTER TABLE users DROP city;

3.2 删除集合列 #

sql
-- 删除List列
ALTER TABLE users DROP tags;

-- 删除Set列
ALTER TABLE users DROP email_list;

-- 删除Map列
ALTER TABLE users DROP preferences;

3.3 删除列注意事项 #

text
删除列注意事项:

✓ 删除后数据不可恢复(除非从备份恢复)
✓ 删除操作创建墓碑(tombstone)
✓ 墓碑在gc_grace_seconds后清除

⚠ 删除后重新添加同名列可能恢复旧数据
⚠ 大量删除可能影响性能

3.4 删除列与墓碑 #

text
删除列的影响:

删除前:
┌─────────────────────────────────────────┐
│ user_id │ name  │ phone      │ email   │
├─────────────────────────────────────────┤
│ 001     │ 张三  │ 138xxxx    │ z@ex.com│
└─────────────────────────────────────────┘

删除phone列:
ALTER TABLE users DROP phone;

删除后(创建墓碑):
┌─────────────────────────────────────────┐
│ user_id │ name  │ [phone墓碑]│ email   │
├─────────────────────────────────────────┤
│ 001     │ 张三  │ <deleted>  │ z@ex.com│
└─────────────────────────────────────────┘

gc_grace_seconds后:
┌─────────────────────────────────────────┐
│ user_id │ name  │            │ email   │
├─────────────────────────────────────────┤
│ 001     │ 张三  │            │ z@ex.com│
└─────────────────────────────────────────┘

四、修改列类型 #

4.1 兼容类型转换 #

sql
-- INT → BIGINT
ALTER TABLE users ALTER age TYPE BIGINT;

-- TEXT → VARCHAR(相同类型)
ALTER TABLE users ALTER name TYPE VARCHAR;

-- FLOAT → DOUBLE
ALTER TABLE products ALTER price TYPE DOUBLE;

4.2 兼容类型列表 #

text
允许的类型转换:

数值类型
├── TINYINT → SMALLINT → INT → BIGINT → VARINT
├── FLOAT → DOUBLE
└── 以上类型 → DECIMAL

文本类型
├── TEXT ↔ VARCHAR
└── ASCII → TEXT

时间类型
└── 各种时间类型之间有限转换

4.3 不兼容类型转换 #

sql
-- 不兼容的类型转换会失败
ALTER TABLE users ALTER age TYPE TEXT;
-- 错误:Cannot convert type int to text

-- 解决方案:
-- 1. 创建新列
ALTER TABLE users ADD age_text TEXT;
-- 2. 迁移数据
-- 3. 删除旧列

五、修改表属性 #

5.1 修改压缩策略 #

sql
-- 修改压缩策略
ALTER TABLE users 
WITH compaction = {
    'class': 'LeveledCompactionStrategy',
    'sstable_size_in_mb': 160
};

-- 修改压缩算法
ALTER TABLE users 
WITH compression = {
    'sstable_compression': 'LZ4Compressor'
};

-- 禁用压缩
ALTER TABLE users 
WITH compression = {
    'sstable_compression': ''
};

5.2 修改缓存配置 #

sql
-- 修改缓存配置
ALTER TABLE users 
WITH caching = {
    'keys': 'ALL',
    'rows_per_partition': '100'
};

5.3 修改其他属性 #

sql
-- 修改注释
ALTER TABLE users WITH comment = '更新后的用户表';

-- 修改gc_grace_seconds
ALTER TABLE users WITH gc_grace_seconds = 172800;

-- 修改默认TTL
ALTER TABLE users WITH default_time_to_live = 86400;

-- 修改多个属性
ALTER TABLE users 
WITH comment = '用户表'
AND gc_grace_seconds = 172800
AND caching = {'keys': 'ALL', 'rows_per_partition': '50'};

5.4 修改压缩策略的影响 #

text
修改压缩策略的影响:

SizeTiered → Leveled
├── 后台逐步转换
├── 短期增加IO
└── 最终更高效的读取

Leveled → SizeTiered
├── 后台逐步转换
├── 可能增加空间使用
└── 适合写入密集场景

六、重命名列 #

6.1 重命名语法 #

sql
-- 重命名列
ALTER TABLE users RENAME old_name TO new_name;

-- 重命名多个列
ALTER TABLE users 
RENAME old_col1 TO new_col1 
AND old_col2 TO new_col2;

6.2 重命名限制 #

text
重命名限制:

✓ 仅支持主键列重命名
✓ 重命名不影响数据
✓ 重命名后查询需要使用新名称

✗ 不能重命名普通列
✗ 不能改变列的顺序

6.3 重命名示例 #

sql
-- 重命名主键列
ALTER TABLE orders 
RENAME order_id TO order_uuid;

-- 重命名复合主键列
ALTER TABLE events 
RENAME device_id TO sensor_id 
AND event_time TO timestamp;

七、验证修改 #

7.1 查看表结构 #

sql
-- 查看修改后的表结构
DESCRIBE TABLE users;

-- 查看列信息
SELECT column_name, type, kind
FROM system_schema.columns
WHERE keyspace_name = 'my_app' AND table_name = 'users';

7.2 查看表属性 #

sql
-- 查看表属性
SELECT * FROM system_schema.tables
WHERE keyspace_name = 'my_app' AND table_name = 'users';

八、最佳实践 #

8.1 修改时机 #

text
最佳修改时机:

推荐
├── 业务低峰期
├── 有充足监控
└── 已备份数据

避免
├── 业务高峰期
├── 大型活动期间
└── 无备份状态

8.2 修改建议 #

text
修改建议:

添加列
├── 可以随时添加
├── 不影响现有数据
└── 无性能影响

删除列
├── 谨慎操作
├── 考虑数据备份
└── 注意墓碑影响

修改类型
├── 确保类型兼容
├── 测试环境验证
└── 准备回滚方案

修改属性
├── 了解影响范围
├── 监控修改效果
└── 必要时回滚

九、常见问题 #

9.1 添加列失败 #

sql
-- 问题:列已存在
ALTER TABLE users ADD name TEXT;
-- 错误:Invalid column name name because it conflicts with an existing column

-- 解决:检查列是否存在
DESCRIBE TABLE users;

9.2 类型转换失败 #

sql
-- 问题:类型不兼容
ALTER TABLE users ALTER age TYPE TEXT;
-- 错误:Cannot alter column "age" type: it cannot be converted from int to text

-- 解决:创建新列迁移数据
ALTER TABLE users ADD age_text TEXT;

9.3 删除列后恢复 #

sql
-- 问题:误删列后想恢复
ALTER TABLE users DROP phone;

-- 解决方案1:从备份恢复
nodetool refresh my_app users

-- 解决方案2:重新添加列(可能恢复旧数据)
ALTER TABLE users ADD phone TEXT;
-- 注意:可能恢复旧数据,但不保证

十、总结 #

修改表要点:

  1. 添加列:随时可添加,不影响现有数据
  2. 删除列:谨慎操作,创建墓碑
  3. 修改类型:仅限兼容类型
  4. 修改属性:压缩、缓存等可随时修改
  5. 重命名列:仅支持主键列
  6. 低峰期操作:减少对业务影响

下一步,让我们学习删除表!

最后更新:2026-03-27