Spanner序列 #
一、序列概述 #
1.1 什么是序列 #
序列(Sequence)是Spanner提供的自增数字生成器,用于生成唯一标识符。
text
序列特点:
├── 生成唯一数字
├── 支持位反转
├── 高性能
├── 分布式友好
└── 避免热点问题
1.2 序列类型 #
text
序列类型:
├── 普通序列
│ ├── 顺序递增
│ └── 可能产生热点
│
└── 位反转序列
├── 随机分布
└── 避免热点问题
二、创建序列 #
2.1 基本语法 #
sql
CREATE SEQUENCE sequence_name
[OPTIONS (sequence_kind = 'kind')];
2.2 创建普通序列 #
sql
-- 创建普通序列
CREATE SEQUENCE user_seq;
-- 使用序列
INSERT INTO users (user_id, name)
VALUES (NEXTVAL('user_seq'), 'John Doe');
-- 获取下一个值
SELECT NEXTVAL('user_seq') AS next_id;
-- 获取当前值(不消耗)
SELECT CURRVAL('user_seq') AS current_id;
2.3 创建位反转序列 #
sql
-- 创建位反转序列
CREATE SEQUENCE user_bit_seq
OPTIONS (sequence_kind = 'bit_reversed_positive');
-- 位反转序列生成的ID分布更均匀
-- 避免写入热点
-- 使用位反转序列
INSERT INTO users (user_id, name)
VALUES (GET_NEXT_SEQUENCE_VALUE(SEQUENCE user_bit_seq), 'John Doe');
2.4 序列选项 #
sql
-- 序列选项
CREATE SEQUENCE custom_seq
OPTIONS (
sequence_kind = 'bit_reversed_positive',
skip_range_min = 1,
skip_range_max = 1000
);
-- skip_range: 跳过指定范围的值
三、使用序列 #
3.1 在INSERT中使用 #
sql
-- 创建表
CREATE TABLE users (
user_id INT64 NOT NULL DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE user_seq)),
name STRING(100) NOT NULL
) PRIMARY KEY (user_id);
-- 插入数据(自动生成ID)
INSERT INTO users (name) VALUES ('John Doe');
INSERT INTO users (name) VALUES ('Jane Doe');
-- 查询结果
SELECT * FROM users;
-- user_id: 1, name: 'John Doe'
-- user_id: 2, name: 'Jane Doe'
3.2 在DEFAULT中使用 #
sql
-- 创建带默认序列值的表
CREATE TABLE orders (
order_id INT64 NOT NULL
DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE order_seq)),
user_id INT64 NOT NULL,
amount FLOAT64
) PRIMARY KEY (order_id);
-- 插入数据
INSERT INTO orders (user_id, amount) VALUES (1, 100.0);
3.3 获取序列值 #
sql
-- 获取下一个值
SELECT NEXTVAL('user_seq') AS next_id;
-- 获取当前值(不消耗)
SELECT CURRVAL('user_seq') AS current_id;
-- 在事务中使用
BEGIN TRANSACTION;
SELECT NEXTVAL('user_seq') AS new_id;
INSERT INTO users (user_id, name) VALUES (new_id, 'Test');
COMMIT;
四、位反转序列 #
4.1 位反转原理 #
text
位反转原理:
├── 原始值: 1, 2, 3, 4, 5, 6, 7, 8
├── 反转后: 1, 3, 5, 7, 2, 4, 6, 8
├── 分布更均匀
└── 避免热点问题
4.2 创建位反转序列 #
sql
-- 创建位反转序列
CREATE SEQUENCE user_bit_seq
OPTIONS (sequence_kind = 'bit_reversed_positive');
-- 使用位反转序列
CREATE TABLE users (
user_id INT64 NOT NULL
DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE user_bit_seq)),
name STRING(100)
) PRIMARY KEY (user_id);
4.3 位反转优势 #
text
位反转序列优势:
├── 避免写入热点
├── 数据分布均匀
├── 提高写入性能
├── 适合分布式场景
└── 仍然保证唯一性
五、序列管理 #
5.1 查看序列 #
sql
-- 查看所有序列
SELECT * FROM INFORMATION_SCHEMA.SEQUENCES;
-- 查看序列详情
SELECT
sequence_name,
sequence_kind,
is_generated
FROM INFORMATION_SCHEMA.SEQUENCES
WHERE sequence_name = 'user_seq';
5.2 修改序列 #
sql
-- Spanner不支持ALTER SEQUENCE
-- 需要删除重建
-- 删除序列
DROP SEQUENCE user_seq;
-- 重新创建
CREATE SEQUENCE user_seq
OPTIONS (sequence_kind = 'bit_reversed_positive');
5.3 删除序列 #
sql
-- 删除序列
DROP SEQUENCE user_seq;
-- 如果存在则删除
DROP SEQUENCE IF EXISTS user_seq;
-- 注意: 如果序列被表使用,需要先修改表
六、序列性能 #
6.1 性能考虑 #
text
序列性能因素:
├── 序列类型: 位反转更优
├── 并发访问: 高性能
├── 网络延迟: 影响获取速度
└── 缓存大小: 影响吞吐量
6.2 性能优化 #
text
序列性能优化:
├── 使用位反转序列
├── 批量获取序列值
├── 使用DEFAULT减少调用
├── 避免频繁获取单个值
└── 监控序列使用情况
6.3 批量获取 #
java
// Java批量获取序列值
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.Statement;
DatabaseClient client = spanner.getDatabaseClient(databaseId);
// 批量获取
for (int i = 0; i < 1000; i++) {
long id = client.singleUse()
.executeQuery(Statement.of("SELECT NEXTVAL('user_seq')"))
.next()
.getLong(0);
// 使用id
}
七、序列最佳实践 #
7.1 选择序列类型 #
text
序列类型选择:
├── 单区域小规模: 普通序列
├── 多区域大规模: 位反转序列
├── 高写入场景: 位反转序列
└── 需要有序ID: 普通序列
7.2 设计建议 #
text
序列设计建议:
├── 使用位反转避免热点
├── 使用DEFAULT简化代码
├── 合理命名序列
├── 监控序列使用
└── 规划序列数量
7.3 使用建议 #
text
序列使用建议:
├── 使用GET_NEXT_SEQUENCE_VALUE
├── 避免频繁获取单个值
├── 使用DEFAULT自动生成
├── 处理序列耗尽情况
└── 监控序列状态
八、总结 #
序列类型对比:
| 类型 | 特点 | 使用场景 |
|---|---|---|
| 普通序列 | 顺序递增 | 小规模、需要有序 |
| 位反转序列 | 随机分布 | 大规模、高写入 |
最佳实践:
text
1. 选择合适的序列类型
└── 根据场景选择
2. 使用位反转序列
└── 避免热点问题
3. 使用DEFAULT简化
└── 自动生成ID
4. 监控序列使用
└── 及时发现问题
5. 规划序列数量
└── 避免过多序列
下一步,让我们学习用户权限管理!
最后更新:2026-03-27