随着 Oracle 26ai 的正式发布,数据库领域再度迎来多项革新。其中,“MATERIALIZED generated columns”(物化生成列)的引入尤为引人注目。这一特性与传统的“DEFAULT columns”(默认列)在功能上相似,却存在本质区别。对于 DBA 和开发者而言,如何通过数据字典视图精准区分二者,成为高效管理与调优的关键。本文将对此进行详细解析。
物化生成列 vs. 默认列:概念澄清
在 Oracle 数据库中,默认列(DEFAULT columns) 是指在插入记录时,如果未显式指定该列的值,则自动填充预设的默认值。默认值可以是常量、函数,甚至是序列或表达式(如 SYS_GUID())。然而,默认值仅在新插入时生效,并不会实时更新,也不依赖表中其他列的值。
而 物化生成列(MATERIALIZED generated columns) 是 Oracle 26ai 推出的新类型。它由表中其他列通过表达式计算得出,并且结果会物理存储在磁盘上。与之相对的是传统的虚拟生成列(VIRTUAL generated columns),后者仅在查询时计算,不占用存储空间。物化生成列兼具了计算列的灵活性和索引列的性能优势,尤其适合需要频繁查询复杂计算结果的场景。
两者最易混淆的点在于:物化生成列也可以拥有默认值语法(如 GENERATED ALWAYS AS (expr) MATERIALIZED),而默认列同样可以定义复杂的表达式。但从数据库内部视图来看,Oracle 26ai 提供了清晰的标记。
核心数据字典视图:USER_TAB_COLUMNS 与 ALL_TAB_COLUMNS
在 Oracle 26ai 中,用于描述表列元数据的核心视图依然是 USER_TAB_COLUMNS、ALL_TAB_COLUMNS 和 DBA_TAB_COLUMNS。但针对物化生成列,新增了几个关键字段:
VIRTUAL_COLUMN:该字段依旧存在,值为YES或NO。对于物化生成列,此字段值为YES;对于普通默认列,值为NO。这是最直接的第一道区分标志。DEFAULT_LENGTH:对于默认列,该字段存储默认值的长度(字节数);对于物化生成列,此字段值为空(NULL),因为生成列的定义并非“默认值”而是“生成表达式”。DATA_DEFAULT:存储列的默认值文本(对于默认列)或生成表达式文本(对于生成列)。注意,即使是物化生成列,这里的文本依然是表达式,而非一个静态值。- 新增字段
GENERATION_TYPE:这是 Oracle 26ai 中引入的专用字段,指示生成列的类型。可能的值包括: -'VIRTUAL':传统虚拟生成列。 -'MATERIALIZED':物化生成列。 -NULL:普通列(包括默认列或非生成列)。
因此,要区分物化生成列与默认列,只需查询 USER_TAB_COLUMNS 中的 GENERATION_TYPE 字段即可。
实战示例:SQL 查询区分两者
假设我们有一张名为 product 的表,其中包含以下定义:
CREATE TABLE product (
id NUMBER PRIMARY KEY,
base_price NUMBER,
tax_rate NUMBER DEFAULT 0.1,
final_price NUMBER GENERATED ALWAYS AS (base_price * (1 + tax_rate)) MATERIALIZED,
created_at DATE DEFAULT SYSDATE
);
我们执行以下查询:
SELECT column_name,
data_default,
virtual_column,
default_length,
generation_type
FROM user_tab_columns
WHERE table_name = 'PRODUCT';
结果如下:
| COLUMN_NAME | DATA_DEFAULT | VIRTUAL_COLUMN | DEFAULT_LENGTH | GENERATION_TYPE |
|---|---|---|---|---|
| ID | NULL | NO | NULL | NULL |
| BASE_PRICE | NULL | NO | NULL | NULL |
| TAX_RATE | 0.1 | NO | 3 | NULL |
| FINAL_PRICE | "BASE_PRICE"*(1+"TAX_RATE") | YES | NULL | MATERIALIZED |
| CREATED_AT | SYSDATE | NO | 7 | NULL |
从表中可以清晰看到:
- tax_rate 和 created_at 是默认列:VIRTUAL_COLUMN='NO',DEFAULT_LENGTH 非空,GENERATION_TYPE=NULL。
- final_price 是物化生成列:VIRTUAL_COLUMN='YES',DEFAULT_LENGTH=NULL,GENERATION_TYPE='MATERIALIZED'。
实际应用中的注意事项
对于 DBA 而言,了解这一区分至关重要:
- 存储与性能:物化生成列会占用物理空间,且会在 DML 操作时实时计算并写入。默认列只在插入时计算一次,后续变更(如 UPDATE 默认列值)需显式指定。
- 索引与约束:物化生成列可建立索引、主键或唯一约束,而默认列不能基于表达式建索引(除非使用函数索引)。
- 数据字典依赖:当需要批量迁移或审计表结构时,利用 GENERATION_TYPE 字段可快速过滤出所有物化列,避免将其与普通默认列混淆。
未来展望
Oracle 26ai 通过引入 GENERATION_TYPE 和增强的物化生成列支持,进一步模糊了计算列与存储列的边界。这项特性在数据仓库、实时计算报表等场景中潜力巨大。对于开发者而言,建议在创建表时明确注释列属性,并结合数据字典定期检查,以确保表设计的可维护性。
总而言之,Oracle 26ai 的数据字典视图已为区分物化生成列与默认列提供了完备的“DNA 鉴定”工具。掌握 VIRTUAL_COLUMN 与新增的 GENERATION_TYPE 的组合使用,即可轻松应对这一挑战。