更新数据 #

一、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"

十、总结 #

更新数据要点:

  1. UPSERT语义:UPDATE实际上是更新或插入
  2. 条件更新:使用IF条件保证原子性
  3. 集合操作:支持追加、删除元素
  4. 计数器:专门的计数器更新语法
  5. TTL设置:控制数据过期
  6. 批量更新:同一分区性能更优

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

最后更新:2026-03-27