数据库序列(Sequence)

数据库序列(Sequence) 是一种生成唯一整数序列对象 ,主要用于自动生成主键值唯一标识符

核心概念

序列是一个数据库对象,按照指定的规则(起始值、增量、最大值等)生成一系列唯一的整数。每次调用序列时,都会返回下一个值。

主要特点

1. 唯一性保证

序列生成的每个值都是唯一的

即使在高并发环境下也能保证不重复
2. 独立性

序列独立于表 存在,可以被多个表共享

不依赖于事务 ,即使事务回滚,序列值也不会回退
3. 可配置性

起始值 (START WITH)

增量 (INCREMENT BY)

最小值/最大值 (MINVALUE/MAXVALUE)

是否循环 (CYCLE/NOCYCLE)

缓存大小(CACHE)

不同数据库的实现

Oracle

sql 复制代码
-- 创建序列
CREATE SEQUENCE user_seq
    START WITH 1
    INCREMENT BY 1
    NOCACHE
    NOCYCLE;

-- 使用序列
INSERT INTO users (id, name) VALUES (user_seq.NEXTVAL, '张三');
SELECT user_seq.CURRVAL FROM dual;  -- 查看当前值

PostgreSQL

sql 复制代码
-- 创建序列
CREATE SEQUENCE order_id_seq
    START WITH 1000
    INCREMENT BY 1;

-- 使用序列
INSERT INTO orders (id, amount) 
VALUES (nextval('order_id_seq'), 100.00);

-- 或者在表中直接使用
CREATE TABLE products (
    id SERIAL PRIMARY KEY,  -- 自动创建序列
    name VARCHAR(100)
);

SQL Server

sql 复制代码
-- 创建序列
CREATE SEQUENCE employee_seq
    AS INT
    START WITH 1
    INCREMENT BY 1;

-- 使用序列
INSERT INTO employees (id, name) 
VALUES (NEXT VALUE FOR employee_seq, '李四');

MySQL

MySQL 没有原生的序列对象,但可以通过以下方式实现:

方式1: AUTO_INCREMENT(最常用)

sql 复制代码
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100)
);

方式2: 模拟序列

sql 复制代码
CREATE TABLE sequence_table (
    seq_name VARCHAR(50) PRIMARY KEY,
    current_value INT
);

-- 获取下一个值
UPDATE sequence_table 
SET current_value = LAST_INSERT_ID(current_value + 1) 
WHERE seq_name = 'user_seq';

SELECT LAST_INSERT_ID();

序列 vs 自增主键

注意事项

⚠️ 序列值不连续的情况

事务回滚后 ,已使用的序列值不会回收

数据库重启 可能导致缓存的序列值丢失

高并发 下可能出现跳号

⚠️性能考虑

使用 CACHE 可以提高性能(减少磁盘I/O)

但缓存越大,数据库重启时丢失的序列值越多

序列和索引

序列(Sequence)和索引(Index)是数据库中两个完全不同的概念,它们的用途、工作原理和使用场景都有本质区别。

核心区别对比

详细对比分析

1. 功能目的不同

序列:生成唯一值

sql 复制代码
-- 创建序列用于生成主键
CREATE SEQUENCE user_id_seq
    START WITH 1
    INCREMENT BY 1;

-- 使用序列生成唯一ID
INSERT INTO users (id, name) 
VALUES (user_id_seq.NEXTVAL, '张三');

索引:加速查询

sql 复制代码
-- 在用户名字段上创建索引,加速查询
CREATE INDEX idx_user_name ON users(name);

-- 查询时会使用索引加速
SELECT * FROM users WHERE name = '张三';

2. 工作原理不同

序列的工作方式:

sql 复制代码
序列内部维护一个计数器:

调用 NEXTVAL → 计数器 +1 → 返回新值
当前值: 100 → 调用 NEXTVAL → 返回 101,计数器更新为 101

索引的工作方式:

sql 复制代码
索引是数据的有序副本(以B+树为例):

原始数据:                    索引结构:
id | name                   B+树索引(idx_user_name)
---|--------                root: [李, 王, 张]
1  | 张三                    /      |      \
2  | 李四                  李四    王五   张三,赵六
3  | 王五                    ↑
4  | 赵六                  查询"张三"时,通过树快速定位

查询 "WHERE name='张三'" 
→ 遍历B+树(3层) → 直接定位到数据
→ 无需全表扫描

3. 使用场景不同

序列的典型场景:

sql 复制代码
-- 场景1: 主键自动生成
CREATE TABLE orders (
    id NUMBER PRIMARY KEY,
    order_no VARCHAR2(50),
    amount NUMBER
);

INSERT INTO orders (id, order_no, amount) 
VALUES (order_seq.NEXTVAL, 'ORD20260506001', 1000);

-- 场景2: 订单号生成
SELECT 'ORD' || TO_CHAR(SYSDATE, 'YYYYMMDD') || 
       LPAD(order_seq.NEXTVAL, 8, '0') as order_no
FROM dual;
-- 结果: ORD2026050600000001

-- 场景3: 多表共享ID生成器
INSERT INTO table_a (id) VALUES (common_seq.NEXTVAL);
INSERT INTO table_b (id) VALUES (common_seq.NEXTVAL);
-- 保证跨表的ID唯一性

索引的典型场景:

sql 复制代码
-- 场景1: 加速 WHERE 条件查询
CREATE INDEX idx_email ON users(email);
SELECT * FROM users WHERE email = 'test@example.com';  -- 快速定位

-- 场景2: 加速 ORDER BY 排序
CREATE INDEX idx_create_time ON orders(create_time);
SELECT * FROM orders ORDER BY create_time DESC;  -- 利用索引顺序

-- 场景3: 加速 JOIN 连接
CREATE INDEX idx_order_user_id ON orders(user_id);
SELECT u.name, o.order_no 
FROM users u
JOIN orders o ON u.id = o.user_id;  -- 连接时使用索引

-- 场景4: 唯一性约束
CREATE UNIQUE INDEX idx_unique_phone ON users(phone);
-- 既加速查询,又保证唯一性

4. 性能影响不同

序列的性能特点:

sql 复制代码
// 序列几乎不影响性能
// INSERT 操作:只是获取一个数字,开销极小
Long id = sequenceGenerator.nextValue();  // 内存操作,非常快
insertUser(id, "张三");

✅ 读取:NEXTVAL 操作非常快(尤其是使用 CACHE 时)

✅ 写入:不增加额外的写入开销

⚠️ 并发:高并发下可能成为瓶颈(可通过 CACHE 优化)

索引的性能特点:

sql 复制代码
-- 查询性能提升明显
-- 无索引: 全表扫描 1000万条记录 → 耗时 5秒
SELECT * FROM users WHERE phone = '13800138000';

-- 有索引: B+树查找只需3-4次I/O → 耗时 5毫秒
CREATE INDEX idx_phone ON users(phone);
SELECT * FROM users WHERE phone = '13800138000';

-- 但写入性能下降
INSERT INTO users (...) VALUES (...);  
-- 需要同时更新数据和所有相关索引

✅ 查询:大幅提升 SELECT 性能

❌ 写入:每次 INSERT/UPDATE/DELETE 都要维护索引,降低写入性能

⚠️ 存储:索引占用额外的磁盘空间

5. 维护成本不同

序列的维护:

sql 复制代码
-- 几乎不需要维护
-- 查看序列状态
SELECT sequence_name, last_number, cache_size 
FROM user_sequences 
WHERE sequence_name = 'USER_ID_SEQ';

-- 修改序列(很少需要)
ALTER SEQUENCE user_id_seq INCREMENT BY 2;

索引的维护:

sql 复制代码
-- 需要定期维护
-- 重建索引(碎片整理)
ALTER INDEX idx_user_name REBUILD;

-- 分析索引使用情况
SELECT index_name, leaf_blocks, distinct_keys 
FROM user_indexes 
WHERE table_name = 'USERS';

-- 删除无用索引(减少写入开销)
DROP INDEX idx_unused_column;

总结

相关推荐
Junsir大斗师2 小时前
Nginx服务器代理Postgresql-16后端数据库
数据库·nginx
Je1lyfish2 小时前
CMU15-445 (2025 Fall/2026 Spring) Project#3 - QueryExecution
linux·c语言·开发语言·数据结构·数据库·c++·算法
m0_596749093 小时前
如何防止SQL拼接漏洞_使用PDO对象实现安全的SQL交互
jvm·数据库·python
老纪的技术唠嗑局4 小时前
深度解析 LLM Wiki / Obsidian-Wiki / GBrain:Agent 时代知识的“自组织”与“自进化”
大数据·数据库·人工智能·算法
2301_795099746 小时前
golang如何在Gin中自定义验证器_golang Gin自定义验证器实现方法
jvm·数据库·python
2301_766283446 小时前
如何在MongoDB GridFS中进行按文件大小(length)范围的查询
jvm·数据库·python
萧曵 丶7 小时前
MySQL 高频面试题(由浅到深 完整版,面试必背)
数据库·mysql·面试
czlczl200209257 小时前
MySQL 执行引擎:排序与临时表机制深度解析
数据库·mysql
lifewange8 小时前
DBeaver如何安装
数据库