随着 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_COLUMNSALL_TAB_COLUMNSDBA_TAB_COLUMNS。但针对物化生成列,新增了几个关键字段:

  1. VIRTUAL_COLUMN:该字段依旧存在,值为 YESNO。对于物化生成列,此字段值为 YES;对于普通默认列,值为 NO。这是最直接的第一道区分标志。
  2. DEFAULT_LENGTH:对于默认列,该字段存储默认值的长度(字节数);对于物化生成列,此字段值为空(NULL),因为生成列的定义并非“默认值”而是“生成表达式”。
  3. DATA_DEFAULT:存储列的默认值文本(对于默认列)或生成表达式文本(对于生成列)。注意,即使是物化生成列,这里的文本依然是表达式,而非一个静态值。
  4. 新增字段 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_ratecreated_at 是默认列:VIRTUAL_COLUMN='NO'DEFAULT_LENGTH 非空,GENERATION_TYPE=NULL。 - final_price 是物化生成列:VIRTUAL_COLUMN='YES'DEFAULT_LENGTH=NULLGENERATION_TYPE='MATERIALIZED'

实际应用中的注意事项

对于 DBA 而言,了解这一区分至关重要: - 存储与性能:物化生成列会占用物理空间,且会在 DML 操作时实时计算并写入。默认列只在插入时计算一次,后续变更(如 UPDATE 默认列值)需显式指定。 - 索引与约束:物化生成列可建立索引、主键或唯一约束,而默认列不能基于表达式建索引(除非使用函数索引)。 - 数据字典依赖:当需要批量迁移或审计表结构时,利用 GENERATION_TYPE 字段可快速过滤出所有物化列,避免将其与普通默认列混淆。

未来展望

Oracle 26ai 通过引入 GENERATION_TYPE 和增强的物化生成列支持,进一步模糊了计算列与存储列的边界。这项特性在数据仓库、实时计算报表等场景中潜力巨大。对于开发者而言,建议在创建表时明确注释列属性,并结合数据字典定期检查,以确保表设计的可维护性。

总而言之,Oracle 26ai 的数据字典视图已为区分物化生成列与默认列提供了完备的“DNA 鉴定”工具。掌握 VIRTUAL_COLUMN 与新增的 GENERATION_TYPE 的组合使用,即可轻松应对这一挑战。