目录
[ROWID 的基本概念](#ROWID 的基本概念)
[INTEGER PRIMARY KEY 的机制](#INTEGER PRIMARY KEY 的机制)
[INTEGER PRIMARY KEY 的潜在问题](#INTEGER PRIMARY KEY 的潜在问题)
[AUTOINCREMENT 的工作方式](#AUTOINCREMENT 的工作方式)
ROWID 的基本概念
SQLite 中的 ROWID 是一个隐藏列,用于标识表中的每一行。其本质是一个 64 位整数,通常由 SQLite 引擎自动分配。如果没有显式的主键定义,ROWID 会成为行的唯一标识。例如:
sql
CREATE TABLE packages (recipient TEXT, address TEXT);
隐藏的 ROWID 结构如下:
| ROWID | recipient | address |
|---|---|---|
| 1 | 张三 | 北京市朝阳区 |
| 2 | 李四 | 上海市浦东区 |
INTEGER PRIMARY KEY 的机制
定义 INTEGER PRIMARY KEY 的列会直接映射到 ROWID。这种设计提供了高效的查询性能。例如:
sql
CREATE TABLE express (
express_id INTEGER PRIMARY KEY,
recipient TEXT,
address TEXT
);
插入数据时,未指定的 express_id 会自动分配为 ROWID 值:
sql
INSERT INTO express (recipient, address) VALUES ('张三', '北京'); -- express_id=1
INSERT INTO express (recipient, address) VALUES ('李四', '上海'); -- express_id=2
性能优势体现在底层直接通过内存地址定位数据,避免额外索引开销。
INTEGER PRIMARY KEY 的潜在问题
删除记录后可能导致 ID 重用。例如:
sql
DELETE FROM express WHERE express_id=2;
INSERT INTO express (recipient, address) VALUES ('王五', '广州'); -- express_id 可能为2
这种特性适用于临时数据或日志系统,但对于需要严格唯一性的场景(如银行流水)存在风险。
AUTOINCREMENT 的工作方式
AUTOINCREMENT 确保 ID 严格递增且不被重用。其实现依赖 sqlite_sequence 表记录当前最大 ID。例如:
sql
CREATE TABLE bank_flow (
flow_id INTEGER PRIMARY KEY AUTOINCREMENT,
amount REAL,
time TEXT
);
操作示例:
- 初始插入记录的
flow_id为 1 和 2; - 删除
flow_id=2后; - 新插入记录的
flow_id强制为 3。
性能影响主要来自每次插入需查询和更新 sqlite_sequence 表。
使用场景的选择建议
-
临时数据/日志系统
选择
INTEGER PRIMARY KEY,允许 ID 重用以提升性能。 -
金融交易/订单系统
选择
INTEGER PRIMARY KEY AUTOINCREMENT,确保 ID 唯一性和递增性。 -
非整数主键场景
避免使用
TEXT主键,因其查询效率显著低于整数类型。
关键差异总结
| 特性 | INTEGER PRIMARY KEY | AUTOINCREMENT |
|---|---|---|
| ID 重用 | 允许 | 禁止 |
| 性能 | 更高(直接使用 ROWID) | 较低(需维护序列表) |
| 适用场景 | 日志/临时数据 | 订单/金融记录 |
通过快递单号和银行流水的场景对比,清晰展示了两者在实现唯一标识时的不同取舍。