IDENTITY列比序列+触发器快约15%且内存低20%,因绕过触发器开销;三种GENERATED模式语义不同,需按需选用;加IDENTITY列应分步操作避免阻塞;12c以下可用序列+应用层调用替代,但需注意跳号与连续性问题。
IDENTITY列比序列+触发器快,且省对象
直接看结果:在100万行插入测试中,generated as identity 比传统 sequence + trigger 快约15%,内存消耗低20%。这不是因为算法更先进,而是它绕过了触发器的解析、执行和上下文切换开销——数据库在insert时直接调用内置序列生成逻辑,不走pl/sql引擎。
你也不用再手动维护两个独立对象:order_seq 和 order_id_trigger。删表时,IDENTITY 列关联的隐式序列会自动清理;而序列+触发器方案里,漏删序列是常见运维事故。
三种GENERATED模式决定你能不能插NULL或指定ID
很多人踩坑是因为没看清模式语义,直接套用MySQL思维。关键差异就三条:
-
GENERATED ALWAYS AS IDENTITY:插任何值(包括NULL)都报ORA-32795;UPDATE该列报ORA-32796;唯一安全写法是省略该列 -
GENERATED BY DEFAULT AS IDENTITY:允许显式插具体数字(如INSERT INTO t (id, name) VALUES (100, 'a')),但插NULL会因NOT NULL约束报ORA-01400 -
GENERATED BY DEFAULT ON NULL AS IDENTITY:只有它能接住INSERT INTO t (id, name) VALUES (NULL, 'a'),自动转为序列值——这是做历史数据迁移时最实用的模式
ALTER TABLE加IDENTITY列要小心主键和索引
给已有大表加IDENTITY列不是ADD COLUMN那么简单。如果同时设主键,Oracle会隐式创建唯一索引,这在千万级表上可能卡住DDL数分钟。更麻烦的是,ALTER TABLE ... ADD id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY 会触发全表扫描校验唯一性。
建议分两步操作:
- 先用
ADD id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY加列(不带主键) - 再用
ALTER TABLE ... MODIFY id NOT NULL补约束(此时不会校验历史数据) - 最后建唯一索引并设主键:
ALTER TABLE ... ADD CONSTRAINT pk_t PRIMARY KEY (id)
否则容易在生产环境被阻塞,尤其当表上有未提交事务时。
12c以下版本没法用IDENTITY,但别硬套触发器
Oracle 11g或更老版本确实不支持IDENTITY,但“必须用触发器”是过时认知。你可以只用SEQUENCE + 应用层显式调用seq.NEXTVAL,跳过触发器——这样既避免触发器调试难的问题,又减少数据库端PL/SQL执行负担。
不过要注意:NEXTVAL 在同一个事务中多次调用会跳号,且无法回滚;而IDENTITY列的值分配与事务绑定更紧密,批量插入时行为更可控。
真正容易被忽略的是:IDENTITY列的隐式序列默认缓存20,和手建序列的CACHE 20一样,实例崩溃可能丢号。如果业务真要求绝对连续(比如发票号),无论用哪种方案,都得关缓存并接受性能代价。











