批量操作 #
一、BATCH概述 #
1.1 BATCH特点 #
Cassandra的BATCH语句有以下特点:
text
BATCH特点:
✓ 多个操作作为一个逻辑单元
✓ 支持INSERT/UPDATE/DELETE
✓ 支持条件操作(轻量级事务)
✓ 支持设置TTL和时间戳
1.2 基本语法 #
sql
BEGIN [UNLOGGED | COUNTER] BATCH
[USING option [AND option ...]]
statement [; statement ...]
APPLY BATCH;
二、基本BATCH #
2.1 简单批量操作 #
sql
-- 批量插入
BEGIN BATCH
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '用户1', 'user1@example.com');
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '用户2', 'user2@example.com');
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '用户3', 'user3@example.com');
APPLY BATCH;
2.2 混合操作 #
sql
-- 混合INSERT/UPDATE/DELETE
BEGIN BATCH
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '新用户', 'new@example.com');
UPDATE users SET email = 'updated@example.com'
WHERE user_id = existing_uuid;
DELETE FROM users WHERE user_id = deleted_uuid;
APPLY BATCH;
2.3 多表操作 #
sql
-- 跨表操作
BEGIN BATCH
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '张三', 'zhang@example.com');
INSERT INTO user_stats (user_id, login_count)
VALUES (uuid(), 0);
INSERT INTO audit_log (log_id, action, timestamp)
VALUES (uuid(), 'user_created', toTimestamp(now()));
APPLY BATCH;
三、BATCH类型 #
3.1 LOGGED BATCH(默认) #
sql
-- 默认类型,记录到批处理日志
BEGIN BATCH
INSERT INTO orders (order_id, user_id, amount)
VALUES (uuid(), user_uuid, 100.00);
UPDATE user_stats SET order_count = order_count + 1
WHERE user_id = user_uuid;
APPLY BATCH;
text
LOGGED BATCH特点:
原子性
├── 全部成功或全部失败
├── 写入批处理日志
└── 跨分区保证
性能
├── 有额外开销
├── 适合跨分区操作
└── 操作数量有限制
3.2 UNLOGGED BATCH #
sql
-- 不记录日志,性能更高
BEGIN UNLOGGED BATCH
INSERT INTO logs (log_id, message, timestamp)
VALUES (uuid(), 'log1', toTimestamp(now()));
INSERT INTO logs (log_id, message, timestamp)
VALUES (uuid(), 'log2', toTimestamp(now()));
INSERT INTO logs (log_id, message, timestamp)
VALUES (uuid(), 'log3', toTimestamp(now()));
APPLY BATCH;
text
UNLOGGED BATCH特点:
性能
├── 无日志开销
├── 性能更高
└── 适合同一分区
原子性
├── 不保证原子性
├── 可能部分成功
└── 需要应用层处理
3.3 COUNTER BATCH #
sql
-- 计数器批量更新
BEGIN COUNTER BATCH
UPDATE user_counters
SET login_count = login_count + 1
WHERE user_id = uuid1;
UPDATE user_counters
SET page_views = page_views + 10
WHERE user_id = uuid1;
APPLY BATCH;
四、BATCH选项 #
4.1 TTL设置 #
sql
-- 设置BATCH的TTL
BEGIN BATCH
USING TTL 3600
INSERT INTO sessions (session_id, user_id)
VALUES (uuid(), user_uuid);
INSERT INTO user_sessions (user_id, session_id)
VALUES (user_uuid, uuid());
APPLY BATCH;
4.2 时间戳设置 #
sql
-- 设置时间戳
BEGIN BATCH
USING TIMESTAMP 1704067200000000
INSERT INTO users (user_id, name, email)
VALUES (uuid(), '张三', 'zhang@example.com');
UPDATE user_stats SET user_count = user_count + 1
WHERE stat_id = 'global';
APPLY BATCH;
4.3 组合选项 #
sql
-- 组合TTL和时间戳
BEGIN BATCH
USING TTL 3600 AND TIMESTAMP 1704067200000000
INSERT INTO cache (key, value, created_at)
VALUES ('cache_key', 'cache_value', toTimestamp(now()));
APPLY BATCH;
五、条件BATCH #
5.1 轻量级事务 #
sql
-- 条件批量操作
BEGIN BATCH
UPDATE users
SET email = 'new@example.com'
WHERE user_id = uuid1
IF email = 'old@example.com';
INSERT INTO audit_log (log_id, user_id, action, timestamp)
VALUES (uuid(), uuid1, 'email_change', toTimestamp(now()));
APPLY BATCH;
5.2 条件结果 #
sql
-- 条件BATCH返回结果
BEGIN BATCH
INSERT INTO users (user_id, email, name)
VALUES (uuid(), 'unique@example.com', '张三')
IF NOT EXISTS;
INSERT INTO user_stats (stat_id, user_count)
VALUES ('global', 1)
IF NOT EXISTS;
APPLY BATCH;
-- 返回结果
-- [applied] | user_id | email | name
------------+---------+--------------------+-------
-- True | uuid | unique@example.com | 张三
六、BATCH最佳实践 #
6.1 同分区操作 #
sql
-- 推荐:同一分区的操作
BEGIN UNLOGGED BATCH
INSERT INTO orders (user_id, order_id, amount)
VALUES (user_uuid, uuid(), 100.00);
INSERT INTO orders (user_id, order_id, amount)
VALUES (user_uuid, uuid(), 200.00);
INSERT INTO orders (user_id, order_id, amount)
VALUES (user_uuid, uuid(), 300.00);
APPLY BATCH;
6.2 操作数量限制 #
text
BATCH操作数量建议:
推荐
├── < 20个操作
├── 同一分区
└── UNLOGGED BATCH
警告
├── > 20个操作
├── 跨分区
└── LOGGED BATCH
限制
├── 最大操作数:65535
├── 批量大小:有限制
└── 超时设置
6.3 适用场景 #
text
BATCH适用场景:
推荐使用
├── 同一分区的多个操作
├── 需要原子性的操作
├── 维护反范式化数据
└── 审计日志记录
不推荐使用
├── 大量数据导入
├── 纯粹为了批量插入
├── 跨分区的大量操作
└── 高频批量操作
七、性能考虑 #
7.1 LOGGED vs UNLOGGED #
text
性能对比:
LOGGED BATCH
├── 原子性保证
├── 写入批处理日志
├── 额外存储开销
├── 性能较低
└── 适合跨分区
UNLOGGED BATCH
├── 无原子性保证
├── 无日志开销
├── 性能更高
└── 适合同一分区
7.2 性能优化 #
text
BATCH性能优化:
1. 使用UNLOGGED BATCH
└── 同一分区操作
2. 控制操作数量
└── < 20个操作
3. 避免跨分区
└── 跨分区使用LOGGED
4. 合理设置超时
└── 根据操作复杂度
5. 监控性能
└── 使用tracing分析
八、错误处理 #
8.1 常见错误 #
sql
-- 操作数量超限
-- 错误:Batch too large
-- 超时
-- 错误:Operation timed out
-- 条件不满足
-- 返回 [applied] = False
8.2 重试策略 #
text
重试策略:
LOGGED BATCH
├── 可以安全重试
└── 幂等性保证
UNLOGGED BATCH
├── 需要谨慎重试
└── 可能导致重复
条件BATCH
├── 检查返回结果
└── 根据条件决定
九、监控BATCH #
9.1 查询追踪 #
sql
-- 启用追踪
TRACING ON;
-- 执行BATCH
BEGIN BATCH
INSERT INTO users (user_id, name) VALUES (uuid(), '张三');
INSERT INTO users (user_id, name) VALUES (uuid(), '李四');
APPLY BATCH;
-- 查看追踪结果
9.2 监控指标 #
bash
# 查看BATCH相关指标
nodetool cfstats | grep -i batch
# JMX监控
# org.apache.cassandra.metrics.Batch
十、完整示例 #
10.1 订单创建 #
sql
-- 创建订单并更新统计
BEGIN BATCH
INSERT INTO orders (
user_id, order_id, order_date,
amount, status, created_at
) VALUES (
?, ?, ?, ?, 'pending', toTimestamp(now())
);
INSERT INTO order_items (
order_id, item_id, product_id,
quantity, price
) VALUES (?, ?, ?, ?, ?);
UPDATE user_stats
SET order_count = order_count + 1,
total_amount = total_amount + ?
WHERE user_id = ?;
INSERT INTO audit_log (
log_id, action, entity_type,
entity_id, timestamp
) VALUES (
uuid(), 'order_created', 'order', ?, toTimestamp(now())
);
APPLY BATCH;
10.2 用户注册 #
sql
-- 用户注册(条件插入)
BEGIN BATCH
INSERT INTO users (
user_id, email, name,
password_hash, created_at
) VALUES (
uuid(), ?, ?, ?, toTimestamp(now())
) IF NOT EXISTS;
INSERT INTO user_emails (
email, user_id
) VALUES (?, ?) IF NOT EXISTS;
UPDATE global_stats
SET user_count = user_count + 1
WHERE stat_id = 'global';
APPLY BATCH;
十一、总结 #
批量操作要点:
- BATCH类型:LOGGED、UNLOGGED、COUNTER
- 原子性:LOGGED BATCH保证原子性
- 性能:UNLOGGED性能更高
- 同分区:同分区操作性能最优
- 操作数量:控制在20个以内
- 条件操作:支持轻量级事务
下一步,让我们学习高级查询!
最后更新:2026-03-27