更新数据 #
一、UPDATE概述 #
1.1 UPDATE特点 #
Cassandra的UPDATE语句有以下特点:
text
UPDATE特点:
✓ UPSERT语义(不存在则插入)
✓ 支持条件更新
✓ 支持集合操作
✓ 支持计数器操作
✓ 支持TTL和时间戳
1.2 基本语法 #
sql
UPDATE [keyspace_name.]table_name
[USING option [AND option ...]]
SET assignment [, assignment ...]
WHERE condition
[IF condition];
二、基本更新 #
2.1 简单更新 #
sql
-- 更新单个列
UPDATE users
SET name = '张三更新'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 更新多个列
UPDATE users
SET name = '张三', email = 'zhang_new@example.com', age = 29
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
2.2 UPSERT语义 #
sql
-- 更新不存在的记录(实际上是插入)
UPDATE users
SET name = '新用户', email = 'new@example.com'
WHERE user_id = 660e8400-e29b-41d4-a716-446655440001;
-- 结果:创建新记录
2.3 WHERE条件 #
sql
-- 必须指定完整主键
UPDATE orders
SET status = 'shipped'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000
AND order_id = 660e8400-e29b-41d4-a716-446655440001;
-- 范围更新(仅限聚簇列范围)
UPDATE events
SET processed = true
WHERE device_id = 'device-001'
AND event_time >= '2024-01-01'
AND event_time < '2024-02-01';
三、TTL和时间戳 #
3.1 设置TTL #
sql
-- 更新并设置TTL
UPDATE users
USING TTL 3600
SET name = '临时更新'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 更新特定列的TTL
UPDATE users
SET email = TTL(email) = 7200
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
3.2 设置时间戳 #
sql
-- 设置时间戳
UPDATE users
USING TIMESTAMP 1704067200000000
SET name = '历史更新'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 同时设置TTL和时间戳
UPDATE users
USING TTL 3600 AND TIMESTAMP 1704067200000000
SET name = '带时间戳的更新'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
四、条件更新 #
4.1 IF条件 #
sql
-- 条件更新
UPDATE users
SET email = 'new_email@example.com'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000
IF email = 'old_email@example.com';
-- 多条件更新
UPDATE orders
SET status = 'cancelled'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000
AND order_id = 660e8400-e29b-41d4-a716-446655440001
IF status = 'pending' AND amount < 1000;
4.2 条件更新结果 #
sql
-- 条件更新返回结果
UPDATE users
SET email = 'new@example.com'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000
IF email = 'old@example.com';
-- 返回结果
-- [applied] | email
------------+-----------------
-- True | old@example.com
-- 条件不满足时
-- [applied] | email
------------+-----------------
-- False | different@example.com
4.3 应用场景 #
text
条件更新应用场景:
状态转换
├── 订单状态变更
├── 任务状态更新
└── 工作流状态
乐观锁
├── 基于版本号更新
├── 基于时间戳更新
└── 避免并发冲突
数据一致性
├── 条件检查
└── 原子性保证
五、集合更新 #
5.1 List更新 #
sql
-- 追加元素
UPDATE users
SET tags = tags + ['new_tag']
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 前置添加
UPDATE users
SET tags = ['first'] + tags
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 替换特定位置
UPDATE users
SET tags[0] = 'updated_tag'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 删除元素
UPDATE users
SET tags = tags - ['old_tag']
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
5.2 Set更新 #
sql
-- 添加元素
UPDATE users
SET emails = emails + {'new@example.com'}
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 删除元素
UPDATE users
SET emails = emails - {'old@example.com'}
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
5.3 Map更新 #
sql
-- 添加键值对
UPDATE users
SET preferences = preferences + {'theme': 'light'}
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 更新特定键
UPDATE users
SET preferences['theme'] = 'dark'
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 删除键
DELETE preferences['language']
FROM users
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
六、计数器更新 #
6.1 计数器表 #
sql
-- 创建计数器表
CREATE TABLE user_counters (
user_id UUID PRIMARY KEY,
login_count COUNTER,
page_views COUNTER,
purchase_count COUNTER
);
6.2 计数器操作 #
sql
-- 增加计数
UPDATE user_counters
SET login_count = login_count + 1
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 减少计数
UPDATE user_counters
SET login_count = login_count - 1
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 批量更新计数器
UPDATE user_counters
SET login_count = login_count + 1,
page_views = page_views + 10,
purchase_count = purchase_count + 1
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
6.3 计数器注意事项 #
text
计数器注意事项:
限制
├── 计数器表只能包含主键和计数器列
├── 不能设置TTL
└── 不能条件更新
性能
├── 使用QUORUM一致性级别
├── 避免频繁更新同一计数器
└── 考虑批量更新
设计
├── 使用独立的计数器表
└── 按业务维度分表
七、批量更新 #
7.1 BATCH更新 #
sql
-- 批量更新
BEGIN BATCH
UPDATE users SET name = '张三' WHERE user_id = uuid1;
UPDATE users SET name = '李四' WHERE user_id = uuid2;
UPDATE users SET name = '王五' WHERE user_id = uuid3;
APPLY BATCH;
-- 条件批量更新
BEGIN BATCH
UPDATE users SET email = 'new@example.com'
WHERE user_id = uuid1
IF email = 'old@example.com';
UPDATE user_audit SET action = 'email_change'
WHERE user_id = uuid1;
APPLY BATCH;
7.2 BATCH最佳实践 #
text
BATCH更新最佳实践:
推荐
├── 同一分区的更新
├── 需要原子性的操作
└── 少量操作(< 20条)
不推荐
├── 跨分区的大量更新
├── 纯粹为了批量更新
└── 大量数据修改
八、NULL处理 #
8.1 设置NULL #
sql
-- 设置列为NULL
UPDATE users
SET phone = null
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
-- 设置多列为NULL
UPDATE users
SET phone = null, address = null
WHERE user_id = 550e8400-e29b-41d4-a716-446655440000;
8.2 NULL vs 墓碑 #
text
NULL处理:
设置NULL
├── 创建墓碑(tombstone)
├── 占用存储空间
└── gc_grace_seconds后清理
删除列
├── 同样创建墓碑
└── 效果相同
建议
├── 避免频繁设置NULL
├── 大量NULL影响性能
└── 考虑使用默认值
九、性能优化 #
9.1 更新优化建议 #
text
更新优化建议:
1. 减少更新频率
└── 合并多次更新
2. 使用BATCH
└── 同一分区的批量更新
3. 调整一致性级别
└── ONE提高吞吐量
4. 避免热点
└── 分散更新到不同分区
5. 监控墓碑
└── 避免大量墓碑影响性能
9.2 监控更新 #
bash
# 查看表统计
nodetool tablestats my_app.users
# 查看墓碑情况
nodetool cfstats my_app.users | grep "Tombstones"
十、总结 #
更新数据要点:
- UPSERT语义:UPDATE实际上是更新或插入
- 条件更新:使用IF条件保证原子性
- 集合操作:支持追加、删除元素
- 计数器:专门的计数器更新语法
- TTL设置:控制数据过期
- 批量更新:同一分区性能更优
下一步,让我们学习删除数据!
最后更新:2026-03-27