4 Tables and Table Clusters(4 表与表簇)

本章介绍模式对象并讨论表,表是最常见的模式对象类型。

  • Introduction to Schema Objects(模式对象简介)
    数据库模式是数据结构的逻辑容器,称为模式对象。模式对象的示例包括表和索引。您可以使用 SQL 创建和操作模式对象。

  • Overview of Tables(表概述)
    表是 Oracle 数据库中数据组织的基本单元。

  • Overview of Table Clusters(表簇概述)
    表簇是一组共享公共列并在相同数据块中存储相关数据的表。

  • Overview of Attribute-Clustered Tables(属性聚簇表概述)
    属性聚簇表是一种堆组织表,它根据用户指定的聚簇指令将数据在磁盘上紧密相邻地存储。这些指令指定单个或多个表中的列。

  • Overview of Temporary Tables(临时表概述)
    临时表保存仅在事务或会话期间存在的数据。

  • Overview of External Tables(外部表概述)
    外部表访问外部源中的数据,就像这些数据位于数据库的表中一样。

  • Overview of Blockchain Tables(区块链表概述)
    区块链表是一种仅追加表,专为集中式区块链应用程序设计。

  • Overview of Immutable Tables(不可变表概述)
    不可变表是仅追加表,可防止内部人员的未经授权的数据修改以及因人为错误导致的意外数据修改。

  • Overview of Object Tables(对象表概述)
    对象表是一种特殊的表,其中每一行代表一个对象。

Introduction to Schema Objects(模式对象简介)

数据库模式是数据结构的逻辑容器,称为模式对象。模式对象的示例包括表和索引。您可以使用 SQL 创建和操作模式对象。

本节包含以下主题:

  • About Common and Local User Accounts(关于公用和本地用户帐户)
  • Common and Local Objects(公用和本地对象)
  • Schema Object Types(模式对象类型)
  • Schema Object Storage(模式对象存储)
  • Schema Object Dependencies(模式对象依赖性)
  • Sample Schemas(示例模式)

About Common and Local User Accounts(关于公用和本地用户帐户)

数据库用户帐户具有密码和特定的数据库权限。

User Accounts and Schemas(用户帐户与模式)

每个用户帐户拥有一个同名的模式。该模式包含拥有该模式的用户的数据。例如,hr 用户帐户拥有 hr 模式,该模式包含诸如 employees 表之类的模式对象。在生产数据库中,模式所有者通常代表数据库应用程序,而非个人。

在模式内,每种特定类型的模式对象都有唯一的名称。例如,hr.employees 指的是 hr 模式中的 employees 表。下图描绘了一个名为 hr 的模式所有者以及 hr 模式中的模式对象。

Figure 4-1 HR Schema(图4-1 HR 模式)

Common and Local User Accounts(公用和本地用户帐户)

如果用户帐户拥有定义数据库的对象,则该用户帐户是公用的。非 Oracle 提供的用户帐户要么是本地用户,要么是公用用户。CDB 公用用户是在 CDB 根容器中创建的公用用户。应用程序公用用户是在应用程序根中创建的用户,并且仅在此应用程序容器内是公用的。

下图展示了 CDB 中可能的用户帐户类型。

Figure 4-2 User Accounts in a CDB(图4-2 CDB 中的用户帐户)

CDB 公用用户可以连接到 CDB 中其具有足够权限的任何容器。相比之下,应用程序公用用户只能连接到其创建所在的应用程序根,或者插入到此应用程序根中的 PDB,具体取决于其权限。

  • Common User Accounts(公用用户帐户)
    在系统容器(CDB)或应用程序容器的上下文中,公用用户是在根容器以及此容器内每个现有和未来的 PDB 中具有相同标识的数据库用户。

  • Local User Accounts(本地用户帐户)
    本地用户是非公用用户,只能在单个 PDB 中操作。

Common User Accounts(公用用户帐户)

在系统容器(CDB)或应用程序容器的上下文中,公用用户是在根容器以及此容器内每个现有和未来的 PDB 中具有相同标识的数据库用户。

每个公用用户都可以连接到其容器的根容器以及其具有足够权限的任何 PDB 并执行操作。某些管理任务必须由公用用户执行。示例包括创建 PDB 和拔出 PDB。

例如,SYSTEM 是一个具有 DBA 权限的 CDB 公用用户。因此,SYSTEM 可以连接到 CDB 根容器和数据库中的任何 PDB。您可以在 saas_sales 应用程序容器中创建一个公用用户 saas_sales_admin。在这种情况下,saas_sales_admin 用户只能连接到 saas_sales 应用程序根或 saas_sales 应用程序容器内的应用程序 PDB。

每个公用用户要么是 Oracle 提供的,要么是用户创建的。Oracle 提供的公用用户的示例包括 SYS 和 SYSTEM。每个用户创建的公用用户要么是 CDB 公用用户,要么是应用程序公用用户。

下图显示了两个 PDB(hrpdb 和 salespdb)中的示例用户和模式。SYS 和 c##dba 是在 CDB$ROOT、hrpdb 和 salespdb 中拥有模式的 CDB 公用用户。本地用户 hr 和 rep 存在于 hrpdb 中。本地用户 hr 和 rep 也存在于 salespdb 中。

Figure 4-3 Users and Schemas in a CDB(图4-3 CDB 中的用户与模式)

公用用户具有以下特征:

  • 公用用户可以登录到其具有 CREATE SESSION 权限的任何容器(包括 CDB$ROOT)。
    公用用户无需在每个容器中都具有相同的权限。例如,c##dba 用户可能有权在 hrpdb 和根容器中创建会话,但无权在 salespdb 中创建会话。由于具有适当权限的公用用户可以在容器之间切换,因此根容器中的公用用户可以管理 PDB。

  • 应用程序公用用户在其自身应用程序容器之外的任何容器中都不具有 CREATE SESSION 权限。
    因此,应用程序公用用户仅限于其自身的应用程序容器。例如,在 saas_sales 应用程序中创建的应用程序公用用户只能连接到 saas_sales 应用程序容器中的应用程序根和 PDB。

  • 用户创建的 CDB 公用用户的名称必须遵循其他数据库用户的命名规则。此外,名称必须以 COMMON_USER_PREFIX 初始化参数指定的字符开头,默认为 c## 或 C##。Oracle 提供的公用用户名称和用户创建的应用程序公用用户名称不受此限制。
    任何本地用户名都不能以字符 c## 或 C## 开头。

  • 每个公用用户在其创建所在的容器(系统容器或特定应用程序容器)内的所有 PDB 中都是唯一命名的。
    CDB 公用用户在 CDB 根中定义,但必须能够以相同的身份连接到每个 PDB。应用程序公用用户驻留在应用程序根中,并且可以以相同的身份连接到其容器中的每个应用程序 PDB。

  • Characteristics of Common Users(公用用户的特征)
    每个公用用户要么是 Oracle 提供的,要么是用户创建的。

  • SYS and SYSTEM Accounts(SYS 和 SYSTEM 帐户)
    所有 Oracle 数据库都包含具有管理权限的默认公用用户帐户。

Characteristics of Common Users(公用用户的特征)

每个公用用户要么是 Oracle 提供的,要么是用户创建的。

公用用户帐户具有以下特征:

  • 公用用户可以登录到其具有 CREATE SESSION 权限的任何容器(包括 CDB$ROOT)。
    公用用户无需在每个容器中都具有相同的权限。例如,c##dba 用户可能有权在 hrpdb 和根容器中创建会话,但无权在 salespdb 中创建会话。由于具有适当权限的公用用户可以在容器之间切换,因此根容器中的公用用户可以管理 PDB。

  • 应用程序公用用户在其自身应用程序容器之外的任何容器中都不具有 CREATE SESSION 权限。
    因此,应用程序公用用户仅限于其自身的应用程序容器。例如,在 saas_sales 应用程序中创建的应用程序公用用户只能连接到 saas_sales 应用程序容器中的应用程序根和 PDB。

  • 用户创建的 CDB 公用用户的名称必须遵循其他数据库用户的命名规则。此外,名称必须以 COMMON_USER_PREFIX 初始化参数指定的字符开头,默认为 c## 或 C##。Oracle 提供的公用用户名称和用户创建的应用程序公用用户名称不受此限制。
    任何本地用户名都不能以字符 c## 或 C## 开头。

  • 每个公用用户在其创建所在的容器(系统容器或特定应用程序容器)内的所有 PDB 中都是唯一命名的。
    CDB 公用用户在 CDB 根中定义,但必须能够以相同的身份连接到每个 PDB。应用程序公用用户驻留在应用程序根中,并且可以以相同的身份连接到其容器中的每个应用程序 PDB。

下图显示了两个 PDB(hrpdb 和 salespdb)中的示例用户和模式。SYS 和 c##dba 是在 CDB$ROOT、hrpdb 和 salespdb 中拥有模式的 CDB 公用用户。本地用户 hr 和 rep 存在于 hrpdb 中。本地用户 hr 和 rep 也存在于 salespdb 中。

Figure 4-4 Users and Schemas in a CDB(图4-4 CDB 中的用户与模式)
在这里插入图片描述

相关参考:

  • 《Oracle AI Database Security Guide》(《Oracle AI 数据库安全指南》):了解有关公用用户帐户的信息
  • 《Oracle AI Database Reference》(《Oracle AI 数据库参考》):了解 COMMON_USER_PREFIX

SYS and SYSTEM Accounts(SYS 和 SYSTEM 帐户)

所有 Oracle 数据库都包含具有管理权限的默认公用用户帐户。

管理帐户具有很高的权限,仅供获授权执行诸如启动和停止数据库、管理内存和存储、创建和管理数据库用户等任务的 DBA 使用。

SYS 公用用户帐户在创建数据库时自动创建。此帐户可以执行所有数据库管理功能。SYS 模式存储数据字典的基表和视图。这些基表和视图对于 Oracle AI 数据库的运行至关重要。SYS 模式中的表仅由数据库操作,任何用户都绝不能修改。

SYSTEM 管理帐户也在创建数据库时自动创建。SYSTEM 模式存储显示管理信息的附加表和视图,以及各种 Oracle AI 数据库选项和工具使用的内部表和视图。切勿使用 SYSTEM 模式来存储非管理用户感兴趣的表。

相关参考:

  • 《Oracle AI Database Security Guide》(《Oracle AI 数据库安全指南》):了解有关用户帐户的信息
  • 《Oracle AI Database Administrator‘s Guide》(《Oracle AI 数据库管理员指南》):了解 SYS、SYSTEM 及其他管理帐户

Local User Accounts(本地用户帐户)

本地用户是非公用用户,只能在单个 PDB 中操作。

本地用户具有以下特征:

  • 本地用户特定于某个 PDB,并且可以在该 PDB 中拥有模式。
    在“Characteristics of Common Users(公用用户的特征)”中显示的示例中,hrpdb 上的本地用户 hr 拥有 hr 模式。在 salespdb 上,本地用户 rep 拥有 rep 模式,本地用户 hr 拥有 hr 模式。

  • 本地用户可以管理 PDB,包括打开和关闭它。
    具有 SYSDBA 权限的公用用户可以向本地用户授予 SYSDBA 权限。在这种情况下,被授予权限的用户仍然是本地用户。

  • 一个 PDB 中的本地用户无法登录到另一个 PDB 或 CDB 根容器。
    例如,当本地用户 hr 连接到 hrpdb 时,如果不使用数据库链接,则 hr 无法访问驻留在 salespdb 数据库中的 sh 模式中的对象。同理,当本地用户 sh 连接到 salespdb PDB 时,如果不使用数据库链接,则 sh 无法访问驻留在 hrpdb 中的 hr 模式中的对象。

  • 本地用户的名称不能以字符 c## 或 C## 开头。

  • 本地用户的名称只需在其 PDB 内是唯一的。
    用户名加上包含该用户模式的 PDB 确定了唯一的本地用户。“Characteristics of Common Users(公用用户的特征)”显示,在 hrpdb 上存在一个名为 rep 的本地用户和模式。在 salespdb PDB 上存在一个完全独立的、名为 rep 的本地用户和模式。

下表描述了涉及“Characteristics of Common Users(公用用户的特征)”中 CDB 的场景。每一行描述了前一行操作之后发生的操作。公用用户 SYSTEM 在两个 PDB 中创建本地用户。

Table 4-1 Local Users in a CDB(表4-1 CDB 中的本地用户)

操作(Operation) 描述(Description)
SQL> CONNECT SYSTEM@hrpdb
Enter password: ********
Connected.
SYSTEM 使用服务名 hrpdb 连接到 hrpdb 容器。
SQL> CREATE USER rep IDENTIFIED BY password ;
User created.
SQL> GRANT CREATE SESSION TO rep;
Grant succeeded.
SYSTEM 现在创建一个本地用户 rep,并在此 PDB 中向该用户授予 CREATE SESSION 权限。该用户是本地用户,因为公用用户只能由连接到根容器的公用用户创建。
SQL> CONNECT rep@salespdb
Enter password: *******
ERROR:
ORA-01017: invalid username/password; logon denied
hrpdb 中的本地用户 rep 尝试连接到 salespdb。该尝试失败,因为 rep 在 PDB salespdb 中不存在。
SQL> CONNECT SYSTEM@salespdb
Enter password: ********
Connected.
SYSTEM 使用服务名 salespdb 连接到 salespdb 容器。
SQL> CREATE USER rep IDENTIFIED BY password ;
User created.
SQL> GRANT CREATE SESSION TO rep;
Grant succeeded.
SYSTEM 在 salespdb 中创建一个本地用户 rep,并在此 PDB 中向该用户授予 CREATE SESSION 权限。因为本地用户的名称只需在其 PDB 内是唯一的,所以名为 rep 的用户可以同时存在于 salespdb 和 hrpdb 中。
SQL> CONNECT rep@salespdb
Enter password: *******
Connected.
rep 用户成功登录到 salespdb。

相关参考:
《Oracle AI Database Security Guide》(《Oracle AI 数据库安全指南》):了解有关本地用户帐户的信息

Common and Local Objects(公用和本地对象)

公用对象在 CDB 根或应用程序根中定义,并且可以使用元数据链接或对象链接进行引用。本地对象是所有非公用对象。

数据库提供的公用对象在 CDBROOT中定义且不可更改。Oracle数据库不支持在CDBROOT 中定义且不可更改。Oracle 数据库不支持在 CDBROOT中定义且不可更改。Oracle数据库不支持在CDBROOT 中创建公用对象。

您可以在应用程序根中创建大多数模式对象——例如表、视图、PL/SQL 和 Java 程序单元、序列等——作为公用对象。如果对象存在于应用程序根中,则它被称为应用程序公用对象。

本地用户可以拥有公用对象。同样,公用用户可以拥有本地对象,但仅当该对象不是数据链接或元数据链接,且既不是元数据链接也不是数据链接时才可以。

相关参考:
《Oracle AI Database Security Guide》(《Oracle AI 数据库安全指南》):了解有关公用对象权限管理的更多信息

Schema Object Types(模式对象类型)

Oracle SQL 使您能够创建和操作许多其他类型的模式对象。

下表显示了主要的模式对象类型。

Table 4-2 Schema Objects(表4-2 模式对象)

对象(Object) 描述(Description) 了解更多(To Learn More)
表(Table) 表以行的形式存储数据。表是关系数据库中最重要的模式对象。 “Overview of Tables(表概述)”
索引(Indexes) 索引是包含表或表簇中每个索引行条目的模式对象,可提供直接、快速的行访问。Oracle AI 数据库支持多种类型的索引。索引组织表是一种数据存储在索引结构中的表。 “Indexes and Index-Organized Tables(索引与索引组织表)”
分区(Partitions) 分区是大型表和索引的组成部分。每个分区都有自己的名称,并可选地具有自己的存储特性。 “Overview of Partitions(分区概述)”
视图(Views) 视图是一个或多个表或其他视图中数据的定制化展现。您可以将其视为存储的查询。视图实际上不包含数据。 “Overview of Views(视图概述)”

Table 4-2 (Cont.) Schema Objects(表4-2 (续)模式对象)

对象(Object) 描述(Description) 了解更多(To Learn More)
序列(Sequences) 序列是一个可供多个用户共享以生成整数的用户创建对象。通常,您使用序列来生成主键值。 “Overview of Sequences(序列概述)”
维度(Dimensions) 维度定义列集对之间的父子关系,其中列集的所有列都必须来自同一个表。维度通常用于对客户、产品和时间等数据进行分类。 “Overview of Dimensions(维度概述)”
同义词(Synonyms) 同义词是另一个模式对象的别名。因为同义词只是一个别名,所以除了在数据字典中的定义之外,它不需要任何存储。 “Overview of Synonyms(同义词概述)”
PL/SQL 子程序和包(PL/SQL subprograms and packages) PL/SQL 是 Oracle 对 SQL 的过程化扩展。PL/SQL 子程序是一个命名的 PL/SQL 块,可以使用一组参数进行调用。PL/SQL 包将逻辑相关的 PL/SQL 类型、变量和子程序组合在一起。 “PL/SQL Subprograms(PL/SQL 子程序)”

其他类型的对象也存储在数据库中,并可以使用 SQL 语句创建和操作,但不包含在模式中。这些对象包括数据库用户帐户、角色、上下文和字典对象。

相关参考:

  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理模式对象
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关模式对象和数据库对象的更多信息

Schema Object Storage(模式对象存储)

某些模式对象将数据存储在一种称为段的逻辑存储结构中。例如,非分区堆组织表或索引会创建一个段。

其他模式对象,例如视图和序列,仅由元数据组成。本主题仅描述具有段的模式对象。

Oracle AI 数据库将模式对象逻辑地存储在表空间中。模式与表空间之间没有关系:一个表空间可以包含来自不同模式的对象,而一个模式的对象可以包含在不同的表空间中。每个对象的数据物理地包含在一个或多个数据文件中。

下图显示了表段和索引段、表空间以及数据文件的一种可能配置。一个表的数据段跨越了两个数据文件,这两个数据文件都是同一个表空间的一部分。一个段不能跨越多个表空间。

Figure 4-5 Segments, Tablespaces, and Data Files(图4-5 段、表空间和数据文件)

相关参考:

  • “Logical Storage Structures(逻辑存储结构)”:了解有关表空间和段的信息
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理模式对象的存储

Schema Object Dependencies(模式对象依赖性)

某些模式对象会引用其他对象,从而产生模式对象依赖性。

例如,一个视图包含一个引用表或视图的查询,而一个 PL/SQL 子程序调用其他子程序。如果对象 A 的定义引用了对象 B,那么 A 是依赖于 B 的对象,而 B 是 A 的被引用对象。

Oracle AI 数据库提供了一种自动机制,以确保依赖对象始终与其被引用对象保持同步。当您创建一个依赖对象时,数据库会跟踪该依赖对象与其被引用对象之间的依赖关系。当被引用对象发生可能影响依赖对象的更改时,数据库会将依赖对象标记为无效。例如,如果用户删除了一个表,那么任何基于该已删除表的视图都将不可用。

无效的依赖对象必须根据被引用对象的新定义进行重新编译,然后才能使用。当引用无效的依赖对象时,会自动进行重新编译。

为了说明模式对象如何产生依赖关系,以下示例脚本创建了一个表 test_table,然后创建了一个查询该表的过程:

CREATE TABLE test_table ( col1 INTEGER, col2 INTEGER );
CREATE OR REPLACE PROCEDURE test_proc
AS
BEGIN
 FOR x IN ( SELECT col1, col2 FROM test_table )
 LOOP
   -- 处理数据
   NULL;
 END LOOP;
END;
/

以下对过程 test_proc 状态的查询显示它是有效的:

SQL> SELECT OBJECT_NAME, STATUS FROM USER_OBJECTS WHERE OBJECT_NAME = 'TEST_PROC';
 
OBJECT_NAME STATUS
----------- -------
TEST_PROC   VALID

在向 test_table 添加 col3 列之后,该过程仍然有效,因为该过程不依赖于该列:

SQL> ALTER TABLE test_table ADD col3 NUMBER;
 
Table altered.
 
SQL> SELECT OBJECT_NAME, STATUS FROM USER_OBJECTS WHERE OBJECT_NAME = 'TEST_PROC';
 
OBJECT_NAME STATUS
----------- -------
TEST_PROC   VALID

但是,更改 test_proc 过程所依赖的 col1 列的数据类型会使该过程失效:

SQL> ALTER TABLE test_table MODIFY col1 VARCHAR2(20);
 
Table altered.
 
SQL> SELECT OBJECT_NAME, STATUS FROM USER_OBJECTS WHERE OBJECT_NAME = 'TEST_PROC';
 
OBJECT_NAME STATUS
----------- -------
TEST_PROC   INVALID

运行或重新编译该过程使其再次有效,如以下示例所示:

SQL> EXECUTE test_proc
 
PL/SQL procedure successfully completed.
 
SQL> SELECT OBJECT_NAME, STATUS FROM USER_OBJECTS WHERE OBJECT_NAME = 'TEST_PROC';
 
OBJECT_NAME STATUS
----------- -------
TEST_PROC   VALID

相关参考:
《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》)和《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解如何管理模式对象依赖性

Sample Schemas(示例模式)

Oracle 数据库可能包含示例模式,这是一组相互关联的模式,使 Oracle 文档和 Oracle 教学材料能够展示常见的数据库任务。

hr 示例模式包含有关员工、部门和地点、工作历史等信息。下图描绘了 hr 中表的实体关系图。本手册中的大多数示例都使用此模式中的对象。

Figure 4-6 HR Schema(图4-6 HR 模式)

相关参考:
《Oracle AI Database Sample Schemas》(《Oracle AI 数据库示例模式》):了解如何安装示例模式

Overview of Tables(表概述)

表是 Oracle 数据库中数据组织的基本单元。

表描述一个实体,实体是指必须记录其信息的重要事物。例如,员工可以是一个实体。

Oracle AI 数据库表分为以下基本类别:

  • 关系表(Relational tables)
    关系表具有简单的列,是最常见的表类型。示例 4-1 显示了一个关系表的 CREATE TABLE 语句。

  • 对象表(Object tables)
    其列对应于对象类型的顶级属性。请参阅“Overview of Object Tables(对象表概述)”。

您可以创建具有以下组织特征的关系表:

  • 堆组织表不按任何特定顺序存储行。默认情况下,CREATE TABLE 语句会创建一个堆组织表。
  • 索引组织表根据主键值对行进行排序。对于某些应用程序,索引组织表可以提高性能并更有效地使用磁盘空间。请参阅“Overview of Index-Organized Tables(索引组织表概述)”。
  • 外部表是一种只读表,其元数据存储在数据库中,但其数据存储在数据库外部。请参阅“Overview of External Tables(外部表概述)”。

表可以是永久的,也可以是临时的。永久表定义和数据在会话之间持续存在。临时表定义以与永久表定义相同的方式持续存在,但数据仅在事务或会话期间存在。临时表在必须临时保存结果集的应用程序中很有用,这可能是因为结果集是通过运行多个操作构建的。

  • Columns(列)
    表定义包括表名和一组列。

  • Rows(行)
    行是对应于表中一条记录的列信息的集合。

  • Example: CREATE TABLE and ALTER TABLE Statements(示例:CREATE TABLE 和 ALTER TABLE 语句)
    用于创建表的 Oracle SQL 语句是 CREATE TABLE。

  • Oracle Data Types(Oracle 数据类型)
    每个列都有一个数据类型,该数据类型与特定的存储格式、约束和有效的值范围相关联。值的数据类型将一组固定的属性与该值相关联。

  • Integrity Constraints(完整性约束)
    完整性约束是一个命名的规则,用于限制表中一个或多个列的值。

  • Table Storage(表存储)
    Oracle AI 数据库使用表空间中的数据段来保存表数据。

  • Table Compression(表压缩)
    数据库可以使用表压缩来减少表所需的存储量。

相关参考:
《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理表

Columns(列)

表定义包括表名和一组列。

列标识了表所描述的实体的一个属性。例如,employees 表中的 employee_id 列指的是员工实体的员工 ID 属性。

通常,在创建表时,您需要为每个列指定列名、数据类型和宽度。例如,employee_id 的数据类型是 NUMBER(6),这表明此列只能包含最多 6 位数字宽度的数值数据。宽度可以由数据类型预先确定,如 DATE。

  • Virtual Columns(虚拟列)
    表可以包含一个虚拟列,也称为表达式列。表达式列可以是虚拟的(意味着不存储在磁盘上),也可以是物化的(意味着存储在磁盘上)。

  • Invisible Columns(不可见列)
    不可见列是用户指定的列,其值仅在按名称显式指定该列时才可见。您可以向表中添加不可见列,而不会影响现有应用程序,并在必要时使该列可见。

  • Lock-Free Reservation(无锁预留)
    无锁预留允许在从数值列值中添加或减去时,对该数值列值进行多个并发更新,而不会被未提交的更新所阻塞。

Virtual Columns(虚拟列)

表可以包含一个虚拟列,也称为表达式列。表达式列可以是虚拟的(意味着不存储在磁盘上),也可以是物化的(意味着存储在磁盘上)。

虚拟列,也称为表达式列,通过计算一组用户指定的表达式或函数来派生值。一个表可以包含一个或多个这样的列,但始终必须有一个常规列。例如,下面的 EMP 表定义包含根据员工工资除以每年 2080 小时计算出的时薪。

CREATE TABLE emp
(
   emp_id           NUMBER(9)     CONSTRAINT emp_pk PRIMARY KEY,
   emp_last_name    VARCHAR2(30)  CONSTRAINT emp_last_name_nn NOT NULL,
   emp_first_name   VARCHAR2(30)  CONSTRAINT emp_first_name_nn NOT NULL,
   emp_salary       NUMBER(9,2),
   emp_hourly_rate  NUMBER(7,2)   GENERATED ALWAYS AS (emp_salary/2080) VIRTUAL,
   emp_phone_no     VARCHAR2(10)
);

接下来,将值插入到非虚拟列中。

INSERT INTO emp (emp_id, emp_last_name, emp_first_name, emp_salary, emp_phone_no)
VALUES (8291, 'Patel', 'Siddharth', 60000, '6505551234');

当您查询该表时,现在可以看到作为表达式列返回的计算值。

SELECT * FROM emp;
 EMP_ID EMP_LAST_NAME  EMP_FIRST_NAME     EMP_SALARY  EMP_HOURLY_RATE EMP_PHONE_NO
_______ ______________ _______________ _____________ ________________ _____________
   8291 Patel          Siddharth               60000            28.85 6505551234

这样的表达式列可以是虚拟的,也可以物化在磁盘上。对于纯虚拟(表达式)列,列值不占用磁盘空间,而是在访问时按需计算。对于物化表达式列,值将在 DML 时计算并存储在磁盘上。

相关参考:
《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理虚拟列

Invisible Columns(不可见列)

不可见列是用户指定的列,其值仅在按名称显式指定该列时才可见。您可以向表中添加不可见列,而不会影响现有应用程序,并在必要时使该列可见。

通常,不可见列有助于迁移和演进在线应用程序。一个用例可能是,某个应用程序使用 SELECT * 语句查询一个包含三列的表。向该表添加第四列将会破坏该应用程序,因为它期望得到三列数据。添加第四列作为不可见列可以使应用程序正常运行。然后,开发人员可以修改应用程序以处理第四列,并在应用程序上线时使该列可见。

以下示例创建了一个包含不可见列 count 的表 products,然后使该不可见列可见:

CREATE TABLE products ( prod_id INT, count INT INVISIBLE );
ALTER TABLE products MODIFY ( count VISIBLE );

相关参考:

  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理不可见列
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关不可见列的更多信息
Lock-Free Reservation(无锁预留)

无锁预留允许在从数值列值中添加或减去时,对该数值列值进行多个并发更新,而不会被未提交的更新所阻塞。

通过避免更新期间的传统锁定机制,此功能使您能够在频繁并发更新可预留列的情况下减少阻塞,从而极大地改善用户体验。在以前的版本中,当通过加减操作更新某行的列值时,对该行的所有其他更新都会被阻塞,直到事务提交。随着 Oracle AI Database 26ai 中无锁预留功能的引入,您可以通过指定更新可以继续进行的条件,允许事务并发地对同一行的可预留列进行加减操作,而不会相互阻塞。这是通过指定数值列为 RESERVABLE 列并为该列创建 CHECK 约束来实现的。还可能获得额外的吞吐量提升,因为可预留列更新不会锁定行,因此不会阻塞另一个事务并发地更新同一行的非可预留列。

例如,您可以允许对库存量进行加减操作,前提是现有数量足以满足请求,并且不超过我们 100 件的货架空间。只要数量值大于零且小于等于 100,任何对此数量值的此类更新都允许继续进行,而不会被未提交的更新阻塞。加减的数量将通过内部预留机制进行预留和保证,以便事务可以继续进行,而无需等待对同一行的可预留列进行了更早预留的其他事务提交。

表级 CHECK 约束可以同时包含可预留列和非可预留列。在发出更新时获得批准的挂起无锁预留,可能会在事务提交时违反此类约束。如果约束的非可预留列在预留之后的时间里被更新,导致其当前值可能违反 CHECK 约束,就可能发生这种情况。如果违反了约束,则事务将不得不终止。然而,表级约束中的非可预留列通常是很不频繁修改的阈值。货架空间、账户所需的余额和支出限制就是此类阈值的示例。

以下示例创建了一个包含可预留列 qty_on_hand 的表 inventory。qty_on_hand 上的 CHECK 约束规定,库存中的商品数量必须为零或更多,并且不超过该商品的货架容量,这样才能使对 qty_on_hand 的更新继续执行而不会阻塞其他更新。在下面的示例中,创建了带有适当约束的 inventory 表,插入了几行数据,并查询了 inventory 表的数据字典。

CREATE TABLE inventory
( item_id            NUMBER          CONSTRAINT inv_pk PRIMARY KEY,
  item_display_name  VARCHAR2(100)   NOT NULL,
  item_desc          VARCHAR2(2000),
  qty_on_hand        NUMBER          RESERVABLE CONSTRAINT qty_ck CHECK
                                        (qty_on_hand >= 0) NOT NULL,
  shelf_capacity     NUMBER          NOT NULL,
    CONSTRAINT shelf_ck CHECK (qty_on_hand <= shelf_capacity)
);
-- 向 inventory 表插入几行
INSERT INTO inventory VALUES (123, 'Milk', 'Lowfat 2%', 100, 120);
INSERT INTO inventory VALUES (456, 'Bread', 'Multigrain', 50, 100);
INSERT INTO inventory VALUES (789, 'Eggs', 'Organic', 50, 75);
COMMIT;
SELECT * FROM inventory;
-- 检查视图 user_tab_cols 和 user_tables 以检查
-- 表是否是可预留表以及可预留列的名称
SELECT table_name, has_reservable_column
FROM   user_tables
WHERE  table_name = 'INVENTORY';
SELECT column_name, reservable_column
FROM   user_tab_cols
WHERE  table_name = 'INVENTORY'
  AND  reservable_column = 'YES';

多个并发更新可预留列的示例:

  • 事务 1:
    UPDATE inventory
    SET    qty_on_hand = qty_on_hand - 10
    WHERE  item_id = 123;
    
  • 事务 2:
    UPDATE inventory
    SET    qty_on_hand = qty_on_hand + 20
    WHERE  item_id = 123;
    
  • 事务 3:
    UPDATE inventory
    SET    qty_on_hand = qty_on_hand - 30
    WHERE  item_id = 123;
    
  • 事务 2:
    commit;
    
  • 事务 3:
    commit;
    
  • 事务 1:
    commit;
    

可以使用 ALTER TABLE 命令将可预留列添加到表中,并指定一个可选的 CHECK 约束。例如:

ALTER TABLE inventory ADD
(qty_on_hold NUMBER RESERVABLE DEFAULT 0
 CONSTRAINT qty_hold CHECK (qty_on_hold >= 0 and qty_on_hold <= 25));

可以使用以下 ALTER TABLE 命令将可预留列转换为非可预留列。应用程序可以选择强制执行约束,尽管可预留列预留功能已禁用,因此当列转换为非可预留列时,约束不会自动删除。是否删除约束是可选的,具体取决于您的要求。例如:

ALTER TABLE inventory MODIFY (qty_on_hand NOT RESERVABLE);
ALTER TABLE inventory DROP CONSTRAINT qty_ck;

可以使用 ALTER TABLE 命令将非可预留列转换为可预留列。例如:

ALTER TABLE inventory MODIFY
(qty_on_hand RESERVABLE
 CONSTRAINT qty_ck CHECK (qty_on_hand >= 0 and qty_on_hand <= 100));

Rows(行)

行是对应于表中一条记录的列信息的集合。

例如,employees 表中的一行描述了特定员工的属性:员工 ID、姓氏、名字等等。创建表后,您可以使用 SQL 插入、查询、删除和更新行。

Example: CREATE TABLE and ALTER TABLE Statements(示例:CREATE TABLE 和 ALTER TABLE 语句)

用于创建表的 Oracle SQL 语句是 CREATE TABLE。

示例 4-1 CREATE TABLE employees(示例 4-1:创建表 employees)

以下示例显示了 hr 示例模式中 employees 表的 CREATE TABLE 语句。该语句指定了诸如 employee_id、first_name 等列,并为每列指定了诸如 NUMBER 或 DATE 的数据类型。

CREATE TABLE employees
    ( employee_id    NUMBER(6),
      first_name     VARCHAR2(20),
      last_name      VARCHAR2(25)   CONSTRAINT emp_last_name_nn  NOT NULL,
      email          VARCHAR2(25)   CONSTRAINT emp_email_nn      NOT NULL,
      phone_number   VARCHAR2(20),
      hire_date      DATE           CONSTRAINT emp_hire_date_nn  NOT NULL,
      job_id         VARCHAR2(10)   CONSTRAINT emp_job_nn        NOT NULL,
      salary         NUMBER(8,2),
      commission_pct NUMBER(2,2),
      manager_id     NUMBER(6),
      department_id  NUMBER(4),
      CONSTRAINT     emp_salary_min CHECK (salary > 0),
      CONSTRAINT     emp_email_uk   UNIQUE (email)
    ) ;

示例 4-2 ALTER TABLE employees(示例 4-2:修改表 employees)

以下示例显示了一个 ALTER TABLE 语句,该语句向 employees 表添加完整性约束。完整性约束强制执行业务规则,并防止在表中输入无效信息。

ALTER TABLE employees
ADD ( CONSTRAINT emp_emp_id_pk   PRIMARY KEY (employee_id),
      CONSTRAINT emp_dept_fk     FOREIGN KEY (department_id)
                                   REFERENCES departments,
      CONSTRAINT emp_job_fk      FOREIGN KEY (job_id)
                                   REFERENCES jobs (job_id),
      CONSTRAINT emp_manager_fk  FOREIGN KEY (manager_id)
                                   REFERENCES employees
    ) ;

示例 4-3 Rows in the employees Table(示例 4-3:employees 表中的行)

以下示例输出显示了 hr.employees 表的 8 行和 6 列。

EMPLOYEE_ID FIRST_NAME  LAST_NAME      SALARY COMMISSION_PCT DEPARTMENT_ID
----------- ----------- ------------- ------- -------------- -------------
        100 Steven      King            24000                           90
        101 Neena       Kochhar         17000                           90
        102 Lex         De Haan         17000                           90
        103 Alexander   Hunold           9000                           60
        107 Diana       Lorentz          4200                           60
        149 Eleni       Zlotkey         10500             .2            80
        174 Ellen       Abel            11000             .3            80
        178 Kimberely   Grant            7000            .15

前面的输出说明了表、列和行的一些重要特性:

  • 表中的一行描述了一名员工的属性:姓名、工资、部门等。例如,输出中的第一行显示了名为 Steven King 的员工记录。
  • 一列描述了员工的一个属性。在该示例中,employee_id 列是主键,这意味着每个员工都由员工 ID 唯一标识。保证任何两个员工不会具有相同的员工 ID。
  • 非键列可以包含具有相同值的行。在该示例中,员工 101 和 102 的工资值是相同的:17000。
  • 外键列引用同一个表或不同表中的主键或唯一键。在此示例中,department_id 中的值 90 对应于 departments 表的 department_id 列。
  • 字段是行与列的交点。它只能包含一个值。例如,员工 103 的部门 ID 字段包含值 60。
  • 字段可以没有值。在这种情况下,该字段被称为包含空值。员工 100 的 commission_pct 列的值为空,而员工 149 的该字段值为 .2。列允许空值,除非在此列上定义了 NOT NULL 或主键完整性约束,在这种情况下,如果没有此列的值,则无法插入任何行。

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE TABLE 语法和语义

Oracle Data Types(Oracle 数据类型)

每个列都有一个数据类型,该数据类型与特定的存储格式、约束和有效的值范围相关联。值的数据类型将一组固定的属性与该值相关联。

这些属性导致 Oracle AI 数据库以不同于另一种数据类型值的方式处理一种数据类型的值。例如,您可以对 NUMBER 数据类型的值进行乘法运算,但不能对 RAW 数据类型的值进行乘法运算。

创建表时,必须为每个列指定数据类型。随后插入到列中的每个值都采用该列的数据类型。

Oracle AI 数据库提供了几种内置数据类型。最常用的数据类型属于本节中详细介绍的类别。

其他重要的内置类型类别包括 raw、大对象(LOB)和集合。PL/SQL 拥有用于常量和变量的数据类型,其中包括 BOOLEAN、引用类型、复合类型(记录)以及用户定义类型。

  • Character Data Types(字符数据类型)
    字符数据类型以字符串形式存储字母数字数据。最常用的字符数据类型是 VARCHAR2,它是存储字符数据的最有效选项。

  • Numeric Data Types(数值数据类型)
    Oracle AI 数据库数值数据类型存储定点和浮点数、零以及无穷大。某些数值类型还存储作为操作未定义结果的值,称为"非数字"或 NaN。

  • Datetime Data Types(日期时间数据类型)
    日期时间数据类型是 DATE 和 TIMESTAMP。Oracle AI 数据库为时间戳提供全面的时区支持。

  • Rowid Data Types(Rowid 数据类型)
    存储在数据库中的每一行都有一个地址——用于在数据库中定位该行的内部表示。Oracle AI 数据库使用 ROWID 数据类型来存储数据库中每一行的地址(rowid)。

  • Boolean Data Type(布尔数据类型)
    BOOLEAN 数据类型包含不同的真值 True 和 False。

  • Format Models and Data Types(格式模型与数据类型)
    格式模型是一个字符字面量,它描述了存储在字符串中的日期时间或数值数据的格式。格式模型不会更改数据库中值的内部表示。

相关参考:

  • 《Oracle AI Database SecureFiles and Large Objects Developer’s Guide》(《Oracle AI 数据库 SecureFiles 和大对象开发人员指南》)
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解内置 SQL 数据类型
  • 《Oracle AI Database PL/SQL Packages and Types Reference》(《Oracle AI 数据库 PL/SQL 包和类型参考》):了解 PL/SQL 数据类型
  • 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解如何使用内置数据类型
Character Data Types(字符数据类型)

字符数据类型以字符串形式存储字母数字数据。最常用的字符数据类型是 VARCHAR2,它是存储字符数据的最有效选项。

字节值对应于字符编码方案,通常称为字符集。数据库字符集在数据库创建时确定。字符集的示例包括 7 位 ASCII、EBCDIC 和 Unicode UTF-8。

字符数据类型的长度语义可以以字节或字符来衡量。将字符串视为字节序列的处理方式称为字节语义。这是字符数据类型的默认方式。将字符串视为字符序列的处理方式称为字符语义。字符是数据库字符集的一个码点。

  • VARCHAR2 and CHAR Data Types(VARCHAR2 和 CHAR 数据类型)
  • NCHAR and NVARCHAR2 Data Types(NCHAR 和 NVARCHAR2 数据类型)

相关参考:

  • 《Oracle AI Database Globalization Support Guide》(《Oracle AI 数据库全球化支持指南》):了解有关字符集的更多信息
  • 《Oracle AI Database Get Started with Oracle AI Database Development》(《Oracle AI 数据库开发入门》):简要介绍数据类型
  • 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解如何选择字符数据类型
VARCHAR2 and CHAR Data Types(VARCHAR2 和 CHAR 数据类型)

VARCHAR2 数据类型存储可变长度的字符字面量。字面量是一个固定的数据值。例如,‘LILA’、‘St. George Island’ 和 ‘101’ 都是字符字面量;5001 是一个数值字面量。字符字面量用单引号括起来,以便数据库可以将它们与模式对象名称区分开来。

注意:本手册交替使用术语文本字面量、字符字面量和字符串。

当您创建一个带有 VARCHAR2 列的表时,您需要指定最大字符串长度。在示例 4-1 中,last_name 列的数据类型为 VARCHAR2(25),这意味着存储在该列中的任何名称最多为 25 个字节。

对于每一行,Oracle AI 数据库将列中的每个值存储为一个可变长度字段,除非某个值超过了最大长度,在这种情况下数据库会返回一个错误。例如,在单字节字符集中,如果您为一行中的 last_name 列值输入了 10 个字符,那么该行片段中的列只存储 10 个字符(10 个字节),而不是 25 个。使用 VARCHAR2 可以减少空间消耗。

与 VARCHAR2 相比,CHAR 存储固定长度的字符串。当您创建一个带有 CHAR 列的表时,该列需要一个字符串长度。默认值为 1 个字节。数据库使用空格将该值填充到指定长度。

Oracle AI 数据库使用非填充比较语义来比较 VARCHAR2 值,并使用空格填充比较语义来比较 CHAR 值。

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关空格填充和非填充比较语义的详细信息

NCHAR and NVARCHAR2 Data Types(NCHAR 和 NVARCHAR2 数据类型)

NCHAR 和 NVARCHAR2 数据类型存储 Unicode 字符数据。

Unicode 是一种通用编码字符集,可以使用单一字符集存储任何语言的信息。NCHAR 存储与民族字符集相对应的固定长度字符串,而 NVARCHAR2 存储可变长度字符串。

您在创建数据库时指定民族字符集。NCHAR 和 NVARCHAR2 数据类型的字符集必须是 AL16UTF16 或 UTF8。这两种字符集都使用 Unicode 编码。

当您创建一个带有 NCHAR 或 NVARCHAR2 列的表时,最大大小始终采用字符长度语义。字符长度语义是 NCHAR 或 NVARCHAR2 的默认且唯一的长度语义。

相关参考:
《Oracle AI Database Globalization Support Guide》(《Oracle AI 数据库全球化支持指南》):了解有关 Oracle 全球化支持功能的信息

Numeric Data Types(数值数据类型)

Oracle AI 数据库数值数据类型存储定点和浮点数、零以及无穷大。某些数值类型还存储作为操作未定义结果的值,称为"非数字"或 NaN。

Oracle AI 数据库以可变长度格式存储数值数据。每个值都以科学记数法存储,使用 1 个字节存储指数。数据库最多使用 20 个字节存储尾数,尾数是浮点数中包含其有效数字的部分。Oracle AI 数据库不存储前导零和尾随零。

  • NUMBER Data Type(NUMBER 数据类型)
    NUMBER 数据类型存储定点和浮点数。数据库可以存储几乎任何大小的数字。保证此数据在运行 Oracle AI 数据库的不同操作系统之间是可移植的。对于大多数需要存储数值数据的情况,建议使用 NUMBER 数据类型。

  • Floating-Point Numbers(浮点数)
    Oracle AI 数据库专门为浮点数提供了两种数值数据类型:BINARY_FLOAT 和 BINARY_DOUBLE。

NUMBER Data Type(NUMBER 数据类型)

NUMBER 数据类型存储定点和浮点数。数据库可以存储几乎任何大小的数字。保证此数据在运行 Oracle AI 数据库的不同操作系统之间是可移植的。对于大多数需要存储数值数据的情况,建议使用 NUMBER 数据类型。

您可以以 NUMBER (p,s) 的形式指定定点数,其中 p 和 s 指的是以下特性:

  • 精度(Precision)
    精度指定数字的总位数。如果未指定精度,则该列将完全按照应用程序提供的方式存储值,不进行任何舍入。

  • 标度(Scale)
    标度指定从小数点到最低有效位的位数。正标度计算小数点右侧一直到最低有效位(含)的位数。负标度计算小数点左侧一直到最低有效位(不含)的位数。如果在不指定标度的情况下指定精度,例如 NUMBER(6),则标度为 0。

在示例 4-1 中,salary 列的类型为 NUMBER(8,2),因此精度为 8,标度为 2。因此,数据库将 100,000 的工资存储为 100000.00。

Floating-Point Numbers(浮点数)

Oracle AI 数据库专门为浮点数提供了两种数值数据类型:BINARY_FLOAT 和 BINARY_DOUBLE。

这些类型支持 NUMBER 数据类型提供的所有基本功能。但是,NUMBER 使用十进制精度,而 BINARY_FLOAT 和 BINARY_DOUBLE 使用二进制精度,这使得算术计算更快,并且通常可以减少存储需求。

BINARY_FLOAT 和 BINARY_DOUBLE 是近似数值数据类型。它们存储十进制值的近似表示,而不是精确表示。例如,值 0.1 不能由 BINARY_DOUBLE 或 BINARY_FLOAT 精确表示。它们常用于科学计算。它们的行为类似于 Java 和 XMLSchema 中的数据类型 FLOAT 和 DOUBLE。

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关数值类型的精度、标度和其他特性

Datetime Data Types(日期时间数据类型)

日期时间数据类型是 DATE 和 TIMESTAMP。Oracle AI 数据库为时间戳提供全面的时区支持。

  • DATE Data Type(DATE 数据类型)
    DATE 数据类型存储日期和时间。尽管日期时间可以用字符或数字数据类型表示,但 DATE 具有特殊的关联属性。

  • TIMESTAMP Data Type(TIMESTAMP 数据类型)
    TIMESTAMP 数据类型是 DATE 数据类型的扩展。

DATE Data Type(DATE 数据类型)

DATE 数据类型存储日期和时间。尽管日期时间可以用字符或数字数据类型表示,但 DATE 具有特殊的关联属性。

数据库在内部将日期存储为数字。日期存储在固定长度的 7 字节字段中,分别对应世纪、年、月、日、小时、分钟和秒。

注意:日期完全支持算术运算,因此您可以像对数字一样对日期进行加减操作。

数据库根据指定的格式模型显示日期。格式模型是一个字符字面量,它描述了日期时间在字符串中的格式。标准日期格式是 DD-MON-RR,它以 01-JAN-11 的形式显示日期。

RR 类似于 YY(年份的最后两位数字),但返回值的世纪会根据指定的两位数字年份和当前年份的最后两位数字而变化。假设在 1999 年,数据库显示 01-JAN-11。如果日期格式使用 RR,则 11 指定 2011 年;而如果格式使用 YY,则 11 指定 1911 年。您可以在数据库实例级和会话级更改默认日期格式。

Oracle AI 数据库以 24 小时格式存储时间——HH:MI:SS。如果未输入时间部分,则默认情况下,日期字段中的时间为 00:00:00 A.M.。在仅输入时间的情况下,日期部分默认为当月的第一天。

相关参考:

  • 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解有关世纪和日期格式掩码的更多信息
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关日期时间格式代码的信息
  • 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解如何使用日期时间数据类型执行算术运算
TIMESTAMP Data Type(TIMESTAMP 数据类型)

TIMESTAMP 数据类型是 DATE 数据类型的扩展。

TIMESTAMP 除了存储 DATE 数据类型中的信息外,还存储小数秒。TIMESTAMP 数据类型对于存储精确的时间值非常有用,例如在必须跟踪事件顺序的应用程序中。

DATETIME 数据类型 TIMESTAMP WITH TIME ZONE 和 TIMESTAMP WITH LOCAL TIME ZONE 是可识别时区的。当用户选择数据时,该值会根据用户会话的时区进行调整。此数据类型对于跨地理区域收集和评估日期信息非常有用。

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关创建时间戳列以及向其中输入数据的语法详细信息

Rowid Data Types(Rowid 数据类型)

存储在数据库中的每一行都有一个地址——用于在数据库中定位该行的内部表示。Oracle AI 数据库使用 ROWID 数据类型来存储数据库中每一行的地址(rowid)。

Rowid 分为以下类别:

  • 物理 rowid 存储堆组织表、表簇以及表和索引分区中行的地址。
  • 逻辑 rowid 存储索引组织表中行的地址。
  • 外部 rowid 是外部表中的标识符,例如通过网关访问的 DB2 表。它们不是标准的 Oracle AI 数据库 rowid。

一种称为通用 rowid(或 urowid)的数据类型支持所有类型的 rowid。

  • Use of Rowids(Rowid 的用途)
  • ROWID Pseudocolumn(ROWID 伪列)
    Oracle 数据库中的每个表都有一个名为 ROWID 的伪列。
Use of Rowids(Rowid 的用途)

Oracle AI 数据库在内部使用 rowid 来构建索引。

B 树索引(最常见的类型)包含一个按范围划分的有序键列表。每个键都与指向关联行地址的 rowid 关联,以实现快速访问。

最终用户和应用程序开发人员也可以将 rowid 用于几个重要功能:

  • Rowid 是重新访问行的一种快速方法,前提是其 rowid 先前已通过 SELECT 语句检索到。
  • Rowid 提供了查看表组织方式的能力。

虽然您可以创建具有使用 ROWID 数据类型定义的列的表,但不应存储 rowid 并意图在以后阶段使用它们来访问数据。以这种方式使用 rowid 可能会产生不可预测或不正确的结果。由于用户发起或数据库引擎内部的原因,行的 rowid 可能会因多种原因而更改。在这些操作中的任何一个发生之后,您不能依赖 rowid 始终指向同一行或有效行。

ROWID Pseudocolumn(ROWID 伪列)

Oracle 数据库中的每个表都有一个名为 ROWID 的伪列。

伪列的行为类似于表列,但实际上并不存储在表中。您可以从伪列中进行选择,但不能插入、更新或删除它们的值。伪列也类似于无参数的 SQL 函数。无参数函数通常为结果集中的每一行返回相同的值,而伪列通常为每一行返回不同的值。

ROWID 伪列的值是表示每行地址的字符串。这些字符串的数据类型为 ROWID。通过执行 SELECT 或 DESCRIBE 列出表的结构时,此伪列并不明显,也不占用空间。但是,可以使用保留字 ROWID 作为列名,通过 SQL 查询检索每一行的 rowid。

以下示例查询 ROWID 伪列,以显示 employees 表中员工 100 所在行的 rowid:

SQL> SELECT ROWID FROM employees WHERE employee_id = 100;
ROWID
------------------
AAAPecAAFAAAABSAAA

相关参考:

  • “Rowid Format(Rowid 格式)”
  • 《Oracle AI Database Development Guide》(《Oracle AI 数据库开发指南》):了解如何按地址标识行
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关 rowid 类型的信息
Boolean Data Type(布尔数据类型)

BOOLEAN 数据类型包含不同的真值 True 和 False。

除非被 NOT NULL 约束禁止,否则布尔数据类型还支持将真值 UNKNOWN 作为空值。您可以在 Oracle SQL 语法中出现 datatype 的任何位置使用布尔数据类型。

相关参考:

  • 《Oracle AI Database SQL Language Quick Reference》(《Oracle AI 数据库 SQL 语言快速参考》):了解有关布尔数据类型的信息。
Format Models and Data Types(格式模型与数据类型)

格式模型是一个字符字面量,它描述了存储在字符串中的日期时间或数值数据的格式。格式模型不会更改数据库中值的内部表示。

当您将字符串转换为日期或数字时,格式模型决定数据库如何解析该字符串。在 SQL 中,您可以使用格式模型作为 TO_CHAR 和 TO_DATE 函数的参数,以格式化要从数据库返回的值,或者格式化要存储在数据库中的值。

以下语句选择部门 80 中员工的工资,并使用 TO_CHAR 函数将这些工资转换为具有数字格式模型 ‘$99,990.99’ 所指定格式的字符值:

SQL> SELECT last_name employee, TO_CHAR(salary, ' $99,990.99') AS "SALARY"
  2  FROM   employees
  3  WHERE  department_id = 80 AND last_name = 'Russell';
 
EMPLOYEE                  SALARY
------------------------- -----------
Russell                    $14,000.00

以下示例使用带有格式掩码 ‘YYYY MM DD’ 的 TO_DATE 函数将字符串 ‘1998 05 20’ 转换为 DATE 值来更新雇佣日期:

SQL> UPDATE employees
  2  SET hire_date = TO_DATE('1998 05 20','YYYY MM DD')
  3  WHERE last_name = 'Hunold';

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关格式模型的更多信息

Integrity Constraints(完整性约束)

完整性约束是一个命名的规则,用于限制表中一个或多个列的值。

数据完整性规则防止在表中输入无效数据。此外,当存在某些依赖关系时,约束可以防止删除表。

如果启用了约束,则数据库在输入或更新数据时对其进行检查。Oracle AI 数据库会阻止不符合约束的数据被输入。如果禁用了约束,则 Oracle AI 数据库允许不符合约束的数据进入数据库。

在示例 4-1 中,CREATE TABLE 语句为 last_name、email、hire_date 和 job_id 列指定了 NOT NULL 约束。约束子句标识列以及约束的条件。这些约束确保指定的列不包含空值。例如,尝试插入没有工作 ID 的新员工会生成错误。

您可以在创建表时或创建表之后创建约束。如果需要,您可以临时禁用约束。数据库将约束存储在数据字典中。

相关参考:

  • “Data Integrity(数据完整性)”:了解有关完整性约束的信息
  • “Overview of the Data Dictionary(数据字典概述)”:了解有关数据字典的信息
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关 SQL 约束子句的信息

Table Storage(表存储)

Oracle AI 数据库使用表空间中的数据段来保存表数据。

段包含由数据块组成的区。表的数据段(对于表簇则是簇数据段)位于表所有者的默认表空间中,或者位于 CREATE TABLE 语句中指定的表空间中。

  • Table Organization(表组织)
    默认情况下,表被组织为堆,这意味着数据库将行放置在最适合的位置,而不是按用户指定的顺序。因此,堆组织表是无序的行集合。

  • Row Storage(行存储)
    数据库将行存储在数据块中。包含少于 256 列数据的表的每一行都包含在一个或多个行片段中。

  • Rowids of Row Pieces(行片段的 Rowid)
    Rowid 实际上是一个 10 字节的行的物理地址。

  • Storage of Null Values(空值的存储)
    空值是列中缺失的值。空值表示缺失、未知或不适用数据。

相关参考:
“User Segments(用户段)”:了解有关段类型及其创建方式的信息

Table Organization(表组织)

默认情况下,表被组织为堆,这意味着数据库将行放置在最适合的位置,而不是按用户指定的顺序。因此,堆组织表是无序的行集合。

注意:索引组织表使用不同的组织原则。

当用户添加行时,数据库将行放置在数据段中第一个可用的空闲空间中。不能保证按照行插入的顺序检索它们。

hr.departments 表是一个堆组织表。它具有部门 ID、名称、经理 ID 和位置 ID 的列。当插入行时,数据库将它们存储在任何适合的位置。该表段中的一个数据块可能包含以下示例中所示的无序行:

50,Shipping,121,1500
120,Treasury,,1700
70,Public Relations,204,2700
30,Purchasing,114,1700
130,Corporate Tax,,1700
10,Administration,200,1700
110,Accounting,205,1700

对于表中的所有行,列的顺序是相同的。数据库通常按照列在 CREATE TABLE 语句中列出的顺序存储它们,但此顺序不能保证。例如,如果表具有 LONG 类型的列,则 Oracle AI 数据库始终将此列存储在行的最后。此外,如果您向表添加新列,则新列将成为存储的最后一列。

表可以包含虚拟列,与普通列不同,它不占用磁盘空间。数据库通过按需计算一组用户指定的表达式或函数来派生虚拟列中的值。您可以对虚拟列建立索引、收集统计信息并创建完整性约束。因此,虚拟列与非虚拟列非常相似。

相关参考:

  • “Overview of Index-Organized Tables(索引组织表概述)”
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关虚拟列的信息
Row Storage(行存储)

数据库将行存储在数据块中。包含少于 256 列数据的表的每一行都包含在一个或多个行片段中。

如果可能,Oracle AI 数据库将每一行存储为一个行片段。但是,如果所有行数据无法插入到单个数据块中,或者对现有行的更新导致该行超出其数据块的大小,则数据库使用多个行片段来存储该行。表簇中的行包含与非聚簇表中行相同的信息。此外,表簇中的行包含引用它们所属的簇键的信息。

相关参考:
“Data Block Format(数据块格式)”:了解有关数据块组件的信息

Rowids of Row Pieces(行片段的 Rowid)

Rowid 实际上是一个 10 字节的行的物理地址。

堆组织表中的每一行都有一个对于此表唯一的 rowid,该 rowid 对应于行片段的物理地址。对于表簇,位于同一数据块中的不同表中的行可能具有相同的 rowid。

Oracle AI 数据库在内部使用 rowid 来构建索引。例如,B 树索引中的每个键都与一个 rowid 相关联,该 rowid 指向关联行的地址以实现快速访问。物理 rowid 提供了对表行的最快访问,使数据库能够在尽可能少的单次 I/O 中检索到一行。

相关参考:

  • “Rowid Format(Rowid 格式)”:了解有关 rowid 结构的信息
  • “Overview of B-Tree Indexes(B 树索引概述)”:了解有关 B 树索引的类型和结构的信息
Storage of Null Values(空值的存储)

空值是列中缺失的值。空值表示缺失、未知或不适用数据。

如果空值位于具有数据值的列之间,则空值存储在数据库中。在这些情况下,它们需要 1 个字节来存储列的长度(零)。行中的尾随空值不需要存储,因为新的行头会发出信号,表明前一行中的其余列为空。例如,如果表的最后三列为空,则不会为这些列存储数据。

相关参考:
《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解有关空值的更多信息

Table Compression(表压缩)

数据库可以使用表压缩来减少表所需的存储量。

压缩可以节省磁盘空间,减少数据库缓冲区高速缓存中的内存使用,并在某些情况下加快查询执行速度。表压缩对数据库应用程序是透明的。

  • Basic Table Compression and Advanced Row Compression(基本表压缩和高级行压缩)
    基于字典的表压缩为堆组织表提供良好的压缩率。

  • Hybrid Columnar Compression(混合列压缩)
    使用混合列压缩,数据库将一组行的同一列存储在一起。数据块不以行主格式存储数据,而是结合使用行和列两种方法。

  • Memory Speed Hybrid Columnar Compression(内存速度混合列压缩)
    内存速度混合列压缩引入了可以以内存速度处理的磁盘压缩单元格式。

Basic Table Compression and Advanced Row Compression(基本表压缩和高级行压缩)

基于字典的表压缩为堆组织表提供良好的压缩率。

Oracle AI 数据库支持以下类型的基于字典的表压缩:

  • 基本表压缩
    此压缩类型适用于批量加载操作。数据库不压缩使用常规 DML 修改的数据。您必须使用直接路径 INSERT 操作、ALTER TABLE … MOVE 操作或在线表重定义来实现基本表压缩。

  • 高级行压缩
    此压缩类型适用于 OLTP 应用程序,并压缩由任何 SQL 操作操纵的数据。数据库实现了有竞争力的压缩率,同时使应用程序能够在大致相同的时间内执行 DML,就像在未压缩表上执行 DML 一样。

对于上述压缩类型,数据库以行主格式存储压缩行。一行的所有列存储在一起,然后是下一行的所有列,依此类推。数据库将重复值替换为对存储在块开头的符号表的短引用。因此,数据库重新创建未压缩数据所需的信息存储在数据块本身中。

压缩数据块看起来很像普通数据块。大多数适用于常规数据块的数据库特性和功能也适用于压缩块。

您可以在表空间、表、分区或子分区级别声明压缩。如果在表空间级别指定,则默认情况下,在该表空间中创建的所有表都会被压缩。

示例 4-4 表级压缩(Example 4-4 Table-Level Compression)

以下语句对 orders 表应用高级行压缩:

ALTER TABLE oe.orders ROW STORE COMPRESS ADVANCED;

示例 4-5 分区级压缩(Example 4-5 Partition-Level Compression)

以下部分 CREATE TABLE 语句示例为一个分区指定了高级行压缩,为另一个分区指定了基本表压缩:

CREATE TABLE sales (
    prod_id     NUMBER     NOT NULL,
    cust_id     NUMBER     NOT NULL, ... )
 PCTFREE 5 NOLOGGING NOCOMPRESS
 PARTITION BY RANGE (time_id)
 ( partition sales_2013 VALUES LESS THAN(TO_DATE(...)) ROW STORE COMPRESS BASIC,
   partition sales_2014 VALUES LESS THAN (MAXVALUE) ROW STORE COMPRESS ADVANCED );

相关参考:

  • “Row Format(行格式)”:了解值在行中的存储方式
  • “Data Block Compression(数据块压缩)”:了解有关压缩数据块格式的信息
  • 《Oracle AI Database Utilities》(《Oracle AI 数据库实用程序》):了解有关使用 SQL*Loader 进行直接路径加载的信息
  • 《Oracle AI Database Administrator‘s Guide》(《Oracle AI 数据库管理员指南》)和《Oracle AI Database Performance Tuning Guide》(《Oracle AI 数据库性能调优指南》):了解有关表压缩的信息
Hybrid Columnar Compression(混合列压缩)

使用混合列压缩,数据库将一组行的同一列存储在一起。数据块不以行主格式存储数据,而是结合使用行和列两种方法。

将具有相同数据类型和相似特征的列数据存储在一起,可以显著提高压缩所带来的存储节省。数据库压缩由任何 SQL 操作操纵的数据,尽管直接路径加载的压缩级别更高。数据库操作透明地针对压缩对象进行,因此无需更改应用程序。

注意:混合列压缩与内存列存储(IM 列存储)密切相关。主要区别在于混合列压缩优化磁盘存储,而 IM 列存储优化内存存储。

  • Types of Hybrid Columnar Compression(混合列压缩的类型)
    如果您的底层存储支持混合列压缩,则可以根据您的要求指定不同的压缩类型。

  • Compression Units(压缩单元)
    混合列压缩使用称为压缩单元的逻辑结构来存储一组行。

  • DML and Hybrid Columnar Compression(DML 与混合列压缩)
    混合列压缩对不同类型 DML 操作中的行锁定有影响。

相关参考:
“In-Memory Area(内存中区域)”:了解有关 IM 列存储的更多信息

Types of Hybrid Columnar Compression(混合列压缩的类型)

如果您的底层存储支持混合列压缩,则可以根据您的要求指定不同的压缩类型。

压缩选项包括:

  • 仓库压缩(Warehouse compression)
    此压缩类型针对节省存储空间进行了优化,适用于数据仓库应用程序。

  • 存档压缩(Archive compression)
    此压缩类型针对最大压缩级别进行了优化,适用于历史数据和不更改的数据。

混合列压缩针对 Oracle Exadata 存储上的数据仓库和决策支持应用程序进行了优化。Oracle Exadata 利用 Oracle Exadata 存储服务器固有的处理能力、内存和 Infiniband 网络带宽,最大限度地提高了对使用混合列压缩的表的查询性能。

其他 Oracle 存储系统支持混合列压缩,并提供与 Oracle Exadata 存储相同的空间节省,但不能提供相同级别的查询性能。对于这些存储系统,混合列压缩非常适合对不经常访问的旧数据进行数据库内归档。

Compression Units(压缩单元)

混合列压缩使用称为压缩单元的逻辑结构来存储一组行。

当您将数据加载到表中时,数据库以列格式存储行组,每列的值一起存储和压缩。在数据库压缩了一组行的列数据之后,数据库会将这些数据放入压缩单元中。

例如,您对一个 daily_sales 表应用混合列压缩。每天结束时,您向表中填充商品和销售数量,商品 ID 和日期构成复合主键。下表显示了 daily_sales 中的一个行子集。

Table 4-3 Sample Table daily_sales(表4-3 示例表 daily_sales)

Item_ID Date Num_Sold Shipped_From Restock
1000 01-JUN-18 2 WAREHOUSE1 Y
1001 01-JUN-18 0 WAREHOUSE3 N
1002 01-JUN-18 1 WAREHOUSE3 N
1003 01-JUN-14 0 WAREHOUSE2 N
1004 01-JUN-18 2 WAREHOUSE1 N
1005 01-JUN-18 1 WAREHOUSE2 N

假设这个行子集存储在一个压缩单元中。混合列压缩将每列的值存储在一起,然后使用多种算法来压缩每一列。数据库根据多种因素选择算法,包括列的数据类型、列中实际值的基数以及用户选择的压缩级别。

如下图所示,每个压缩单元可以跨多个数据块。特定列的值可能跨多个块,也可能不跨多个块。

Figure 4-7 Compression Unit(图4-7 压缩单元)

如果混合列压缩没有带来空间节省,那么数据库将以 DBMS_COMPRESSION.COMP_BLOCK 格式存储数据。在这种情况下,数据库对驻留在混合列压缩段中的块应用 OLTP 压缩。

相关参考:

  • “Row Locks (TX)(行锁 (TX))”
  • 《Oracle AI Database Licensing Information User Manual》(《Oracle AI 数据库许可信息用户手册》):了解有关混合列压缩的许可要求
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何使用混合列压缩
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE TABLE 语法和语义
  • 《Oracle AI Database PL/SQL Packages and Types Reference》(《Oracle AI 数据库 PL/SQL 包和类型参考》):了解 DBMS_COMPRESSION 包
DML and Hybrid Columnar Compression(DML 与混合列压缩)

混合列压缩对不同类型 DML 操作中的行锁定有影响。

直接路径加载和常规插入(Direct Path Loads and Conventional Inserts)

在将数据加载到使用混合列压缩的表中时,您可以使用常规插入或直接路径加载。直接路径加载会锁定整个表,从而降低并发性。

从 Oracle Database 12c 第 2 版 (12.2) 开始,增加了对混合列压缩格式的常规数组插入的支持。常规数组插入的优点是:

  • 插入的行使用行级锁,从而提高了并发性。
  • 自动数据优化(ADO)和热图支持行级策略的混合列压缩。因此,即使段的其他部分发生 DML 活动,数据库也可以对符合条件的块使用混合列压缩。

当应用程序使用常规数组插入时,Oracle AI 数据库在满足以下条件时将行存储在压缩单元中:

  • 表存储在 ASSM 表空间中。
  • 兼容级别为 12.2.0.1 或更高版本。
  • 表定义满足现有的混合列压缩表约束,包括没有 LONG 类型的列,以及没有行依赖性。

常规插入会生成重做和撤销。因此,由常规 DML 语句创建的压缩单元会随 DML 一起回滚或提交。数据库会自动执行索引维护,就像对存储在常规数据块中的行一样。

从 Oracle AI Database 26ai 开始,自动存储压缩使 Oracle AI 数据库能够最初以未压缩格式直接加载数据,然后在后台逐步将行移动到混合列压缩格式。这对用户是透明的,同时提高了 ETL 性能并保持了快速的查询性能。

更新和删除(Updates and Deletes)

默认情况下,如果对压缩单元中的任何行应用更新或删除操作,数据库会锁定该压缩单元中的所有行。为避免此问题,您可以选择为表启用行级锁定。在这种情况下,数据库仅锁定受更新或删除操作影响的行。

相关参考:

  • Automatic Segment Space Management(自动段空间管理)
  • Row Locks (TX)(行锁 (TX))
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何执行常规插入
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 INSERT 语句
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解使用 COMPRESS_IMMEDIATE 提示的信息
  • 《Oracle AI Database VLDB and Partitioning Guide》(《Oracle AI 数据库 VLDB 与分区指南》):了解使用自动存储压缩的信息
Memory Speed Hybrid Columnar Compression(内存速度混合列压缩)

内存速度混合列压缩引入了可以以内存速度处理的磁盘压缩单元格式。

与混合列压缩类似,内存速度混合列压缩适用于数据仓库环境。它在数据加载期间将数据转换为面向列的格式并对其进行压缩。关键区别在于,内存速度混合列压缩采用了与内存中列存储和 Exadata 闪存缓存中的 CELLMEMORY 相同的特殊列格式,从而在所有存储层实现高速列扫描和高效的列缓存。此外,内存速度混合列压缩单元比混合列压缩单元大得多,这允许在磁盘上有效使用内存中列格式。

内存速度混合列压缩作为混合列压缩的扩展,通过使用 CREATE TABLE 命令并添加关键字 MEMSPEED 来启用。

示例 4-6 内存速度混合列压缩(Example 4-6 Memory Speed Hybrid Columnar Compression)

以下示例创建启用了内存速度混合列压缩的 orders 表:

CREATE TABLE orders COLUMN STORE COMPRESS FOR MEMSPEED QUERY;

注意:请参阅《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》)了解更多信息。

Overview of Table Clusters(表簇概述)

表簇是一组共享公共列并在相同数据块中存储相关数据的表。

当表被聚簇时,单个数据块可以包含来自多个表的行。例如,一个块可以同时存储来自 employees 表和 departments 表的行,而不是仅来自单个表。

簇键是聚簇的表所共有的一个或多个列。例如,employees 表和 departments 表共享 department_id 列。您在创建表簇时以及创建添加到表簇中的每个表时指定簇键。

簇键值是特定行集合的簇键列的值。包含相同簇键值(例如 department_id=20)的所有数据在物理上存储在一起。无论不同表中有多少行包含该值,每个簇键值只在簇和簇索引中存储一次。

打个比方,假设一位 HR 经理有两个书柜:一个装有员工文件夹的盒子,另一个装有部门文件夹的盒子。用户经常要求特定部门中所有员工的文件夹。为了便于检索,经理将所有盒子重新排列在一个书柜中。她按部门 ID 划分盒子。因此,部门 20 中所有员工的文件夹以及部门 20 本身的文件夹都在一个盒子里;部门 100 中员工的文件夹以及部门 100 的文件夹在另一个盒子里,依此类推。

当表主要被查询(但不修改)并且表中的记录经常一起查询或连接时,请考虑聚簇表。由于表簇将不同表的相关行存储在相同的数据块中,因此使用得当的表簇相比于非聚簇表具有以下优势:

  • 减少了聚簇表连接的磁盘 I/O。
  • 提高了聚簇表连接的访问时间。
  • 存储相关表和索引数据所需的空间更少,因为簇键值不会为每一行重复存储。

通常,在以下情况下不适合聚簇表:

  • 表频繁更新。

  • 表经常需要全表扫描。

  • 表需要截断。

  • Overview of Indexed Clusters(索引簇概述)
    索引簇是使用索引定位数据的表簇。簇索引是簇键上的 B 树索引。在将任何行插入聚簇表之前,必须先创建簇索引。

  • Overview of Hash Clusters(哈希簇概述)
    哈希簇类似于索引簇,但索引键被替换为哈希函数。不存在单独的簇索引。在哈希簇中,数据本身就是索引。

Overview of Indexed Clusters(索引簇概述)

索引簇是使用索引定位数据的表簇。簇索引是簇键上的 B 树索引。在将任何行插入聚簇表之前,必须先创建簇索引。

示例 4-7 创建表簇及相关索引(Example 4-7 Creating a Table Cluster and Associated Index)

假设您创建了簇键为 department_id 的簇 employees_departments_cluster,如以下示例所示:

CREATE CLUSTER employees_departments_cluster
   (department_id NUMBER(4))
SIZE 512;
CREATE INDEX idx_emp_dept_cluster 
   ON CLUSTER employees_departments_cluster;

因为未指定 HASHKEYS 子句,所以 employees_departments_cluster 是一个索引簇。前面的示例在簇键 department_id 上创建了一个名为 idx_emp_dept_cluster 的索引。

示例 4-8 在索引簇中创建表(Example 4-8 Creating Tables in an Indexed Cluster)

您在簇中创建 employees 和 departments 表,并指定 department_id 列作为簇键,如下所示(省略号标记列规范所在的位置):

CREATE TABLE employees ( ... )
   CLUSTER employees_departments_cluster (department_id);
 
CREATE TABLE departments ( ... )
   CLUSTER employees_departments_cluster (department_id);

假设您向 employees 和 departments 表添加行。数据库将每个部门的 employees 表和 departments 表中的所有行物理地存储在相同的数据块中。数据库以堆形式存储行,并使用索引定位它们。

图 4-8 显示了包含 employees 和 departments 的 employees_departments_cluster 表簇。数据库将部门 20 的员工行存储在一起,部门 110 的行存储在一起,依此类推。如果表没有聚簇,那么数据库就不能确保相关的行存储在一起。

Figure 4-8 Clustered Table Data(图4-8 聚簇表数据)

B 树簇索引将簇键值与包含数据的数据块地址(DBA)相关联。例如,键 20 的索引条目显示了包含部门 20 员工数据的块的地址:

20,AADAAAA9d

簇索引是单独管理的,就像非聚簇表上的索引一样,并且可以存在于与表簇不同的表空间中。

相关参考:

  • “Introduction to Indexes(索引简介)”
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何创建和管理索引簇
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE CLUSTER 语法和语义

Overview of Hash Clusters(哈希簇概述)

哈希簇类似于索引簇,但索引键被替换为哈希函数。不存在单独的簇索引。在哈希簇中,数据本身就是索引。

对于索引表或索引簇,Oracle AI 数据库使用存储在单独索引中的键值来定位表行。要查找或存储索引表或表簇中的行,数据库必须执行至少两次 I/O:

  • 一次或多次 I/O 以在索引中查找或存储键值
  • 另一次 I/O 以读取或写入表或表簇中的行

要查找或存储哈希簇中的行,Oracle AI 数据库将哈希函数应用于行的簇键值。生成的哈希值对应于簇中的一个数据块,数据库代表所发出的语句读取或写入该数据块。

哈希是一种可选的存储表数据的方式,用于提高数据检索的性能。当满足以下条件时,哈希簇可能是有益的:

  • 表的查询频率远高于修改频率。

  • 哈希键列经常使用等值条件进行查询,例如 WHERE department_id=20。对于此类查询,簇键值被哈希处理。哈希键值直接指向存储行的磁盘区域。

  • 您可以合理地猜测哈希键的数量以及每个键值存储的数据大小。

  • Hash Cluster Creation(哈希簇的创建)
    要创建哈希簇,您可以使用与索引簇相同的 CREATE CLUSTER 语句,并添加一个哈希键。簇的哈希值数量取决于哈希键。

  • Hash Cluster Queries(哈希簇查询)
    在哈希簇的查询中,数据库决定如何对用户输入的键值进行哈希处理。

  • Hash Cluster Variations(哈希簇变体)
    单表哈希簇是哈希簇的优化版本,一次只支持一个表。哈希键和行之间存在一一映射关系。

  • Hash Cluster Storage(哈希簇存储)
    Oracle AI 数据库为哈希簇分配空间的方式与索引簇不同。

Hash Cluster Creation(哈希簇的创建)

要创建哈希簇,您可以使用与索引簇相同的 CREATE CLUSTER 语句,并添加一个哈希键。簇的哈希值数量取决于哈希键。

簇键,与索引簇的键一样,是簇中的表共享的单个列或复合键。哈希键值是插入到簇键列中的实际或可能的值。例如,如果簇键是 department_id,那么哈希键值可能是 10、20、30 等。

Oracle AI 数据库使用一个哈希函数,该函数接受无限数量的哈希键值作为输入,并将它们排序到有限数量的桶中。每个桶都有一个唯一的数字 ID,称为哈希值。每个哈希值映射到存储与哈希键值(部门 10、20、30 等)对应的行的数据块地址。

在以下示例中,可能存在的部门数量为 100,因此 HASHKEYS 设置为 100:

CREATE CLUSTER employees_departments_cluster
   (department_id NUMBER(4))
SIZE 8192 HASHKEYS 100;

创建 employees_departments_cluster 之后,您可以在簇中创建 employees 和 departments 表。然后,您可以像在索引簇中一样将数据加载到哈希簇中。

相关参考:

  • “Overview of Indexed Clusters(索引簇概述)”
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何创建和管理哈希簇
Hash Cluster Queries(哈希簇查询)

在哈希簇的查询中,数据库决定如何对用户输入的键值进行哈希处理。

例如,用户经常执行如下查询,为 p_id 输入不同的部门 ID 编号:

SELECT *
FROM   employees
WHERE  department_id = :p_id;
 
SELECT * 
FROM   departments 
WHERE  department_id = :p_id;
SELECT * 
FROM   employees e, departments d 
WHERE  e.department_id = d.department_id
AND    d.department_id = :p_id;

如果用户查询 department_id =20 中的员工,那么数据库可能会将此值哈希到桶 77。如果用户查询 department_id =10 中的员工,那么数据库可能会将此值哈希到桶 15。数据库使用内部生成的哈希值来定位包含所请求部门的员工行的数据块。

下图将哈希簇段描绘为水平的一行数据块。如图所示,查询可以在单次 I/O 中检索数据。

Figure 4-9 Retrieving Data from a Hash Cluster(图4-9 从哈希簇检索数据)

哈希簇的一个限制是无法对非索引的簇键进行范围扫描。假设在“Hash Cluster Creation(哈希簇的创建)”中创建的哈希簇不存在单独的索引。对 ID 介于 20 到 100 之间的部门的查询不能使用哈希算法,因为它无法对 20 到 100 之间的每个可能值进行哈希处理。由于没有索引,数据库必须执行全扫描。

相关参考:
“Index Range Scan(索引范围扫描)”

Hash Cluster Variations(哈希簇变体)

单表哈希簇是哈希簇的优化版本,一次只支持一个表。哈希键和行之间存在一一映射关系。

当用户需要通过主键快速访问表时,单表哈希簇可能是有益的。例如,用户经常通过 employee_id 在 employees 表中查找员工记录。

排序哈希簇以这样一种方式存储与哈希函数每个值相对应的行,使得数据库能够高效地按排序顺序返回它们。数据库在内部执行优化排序。对于始终按排序顺序消费数据的应用程序,这种技术可以加快数据检索速度。例如,应用程序可能始终对 orders 表的 order_date 列进行排序。

相关参考:
《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何创建单表哈希簇和排序哈希簇

Hash Cluster Storage(哈希簇存储)

Oracle AI 数据库为哈希簇分配空间的方式与索引簇不同。

在“Hash Cluster Creation(哈希簇的创建)”的示例中,HASHKEYS 指定可能存在的部门数量,而 SIZE 指定与每个部门关联的数据大小。数据库根据以下公式计算存储空间值:

HASHKEYS * SIZE / database_block_size(HASHKEYS * SIZE / 数据库块大小)

因此,如果在“Hash Cluster Creation(哈希簇的创建)”中显示的示例中块大小为 4096 字节,那么数据库至少为哈希簇分配 200 个块。

Oracle AI 数据库不限制您可以插入到簇中的哈希键值的数量。例如,即使 HASHKEYS 为 100,也没有任何因素阻止您在 departments 表中插入 200 个唯一部门。但是,当哈希值的数量超过哈希键的数量时,哈希簇检索的效率会降低。

为了说明检索问题,假设图 4-9 中的块 100 完全填满了部门 20 的行。用户向 departments 表中插入一个 department_id 为 43 的新部门。部门数量超过了 HASHKEYS 值,因此数据库将 department_id 43 哈希到哈希值 77,该值与用于 department_id 20 的哈希值相同。将多个输入值哈希到同一个输出值称为哈希冲突。

当用户为部门 43 向簇中插入行时,数据库无法将这些行存储在块 100 中,因为该块已满。数据库将块 100 链接到一个新的溢出块(例如块 200),并将插入的行存储在新块中。现在,块 100 和块 200 都可以存储任一部门的数据。如图 4-10 所示,现在查询部门 20 或 43 都需要两次 I/O 来检索数据:块 100 及其关联的块 200。您可以通过使用不同的 HASHKEYS 值重新创建簇来解决此问题。

Figure 4-10 Retrieving Data from a Hash Cluster When a Hash Collision Occurs(图4-10 发生哈希冲突时从哈希簇检索数据)

相关参考:
《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理哈希簇中的空间

Overview of Attribute-Clustered Tables(属性聚簇表概述)

属性聚簇表是一种堆组织表,它根据用户指定的聚簇指令将数据在磁盘上紧密相邻地存储。这些指令指定单个或多个表中的列。

指令如下:

  • CLUSTERING ... BY LINEAR ORDER 指令根据指定的列对表中的数据进行排序。
    当查询限定了聚簇子句中指定的列的前缀时,可以考虑使用 BY LINEAR ORDER 聚簇(这是默认方式)。例如,如果对 sh.sales 的查询经常指定客户 ID,或者同时指定客户 ID 和产品 ID,那么您可以使用线性列顺序 cust_id, prod_id 来聚簇表中的数据。

  • CLUSTERING ... BY INTERLEAVED ORDER 指令使用一种特殊的算法对单个或多个表中的数据进行排序,该算法类似于 Z-order 函数,允许减少多列 I/O。
    当查询指定各种列组合时,可以考虑使用 BY INTERLEAVED ORDER 聚簇。例如,如果对 sh.sales 的查询以不同的顺序指定不同的维度,那么您可以根据这些维度中的列来聚簇 sales 表中的数据。

属性聚簇仅适用于直接路径 INSERT 操作。对于常规 DML,它会被忽略。

本节包含以下主题:

  • Advantages of Attribute-Clustered Tables(属性聚簇表的优势)
  • Join Attribute Clustered Tables(连接属性聚簇表)
  • I/O Reduction Using Zones(使用区域减少 I/O)
  • Attribute-Clustered Tables with Linear Ordering(具有线性排序的属性聚簇表)
  • Attribute-Clustered Tables with Interleaved Ordering(具有交错排序的属性聚簇表)

Advantages of Attribute-Clustered Tables(属性聚簇表的优势)

属性聚簇表的主要优势在于减少 I/O,这可以显著降低表扫描的 I/O 成本和 CPU 成本。I/O 减少是通过区域实现的,或者通过聚簇值在磁盘上更紧密的物理邻近度来减少物理 I/O。

属性聚簇表具有以下优势:

  • 您可以根据星型模式中的维度列来聚簇事实表。
    在星型模式中,大多数查询限定维度表而不是事实表,因此按事实表列聚簇并不有效。Oracle AI 数据库支持对维度表中的列进行聚簇。

  • I/O 减少可以在几种不同的场景中发生:

    • 与 Oracle Exadata 存储索引、Oracle 内存中最小/最大值修剪或区域映射一起使用时
    • 在 OLTP 应用程序中,对于限定前缀的查询,并使用具有线性顺序的属性聚簇
    • 对于 BY INTERLEAVED ORDER 聚簇的聚簇列子集
  • 属性聚簇可以改善数据压缩,并以这种方式间接改善表扫描成本。
    当相同的值在磁盘上彼此靠近时,数据库可以更容易地压缩它们。

  • Oracle AI 数据库不会产生索引的存储和维护成本。

相关参考:
《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解属性聚簇表的更多优势

Join Attribute Clustered Tables(连接属性聚簇表)

基于连接列的属性聚簇称为连接属性聚簇。与表簇相比,连接属性聚簇表不会将来自一组表的数据存储在相同的数据库块中。

例如,考虑一个属性聚簇表 sales 与一个维度表 products 连接。sales 表只包含来自 sales 表的行,但行的排序基于从 products 表连接的列的值。适当的连接在数据移动、直接路径插入和 CREATE TABLE AS SELECT 操作期间执行。

相比之下,如果 sales 和 products 在一个标准表簇中,那么数据块将包含来自两个表的行。

相关参考:
《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解有关连接属性聚簇的更多信息

I/O Reduction Using Zones(使用区域减少 I/O)

区域是一组连续的数据块,存储相关列的最小值和最大值。

当 SQL 语句包含对存储在区域中的列的谓词时,数据库会将谓词值与区域中存储的最小值和最大值进行比较。通过这种方式,数据库确定在 SQL 执行期间要读取哪些区域。

I/O 减少是指能够跳过不包含数据库满足查询所需数据的表块或索引块。这种减少可以显著降低表扫描的 I/O 和 CPU 成本。

  • Purpose of Zones(区域的目的)
    对于区域的一个粗略类比,考虑一位销售经理使用一个带有鸽笼式格架的书柜,这些格架类似于数据块。

  • Zone Maps(区域映射)
    区域映射是一种独立的访问结构,它将数据块划分为区域。Oracle AI 数据库将每个区域映射实现为一种物化视图。

  • Zone Map Creation(区域映射创建)
    基本区域映射可以手动或自动创建。

  • How a Zone Map Works: Example(区域映射的工作原理:示例)
    此示例说明区域映射如何在其谓词包含常量的查询中修剪数据。

Purpose of Zones(区域的目的)

对于区域的一个粗略类比,考虑一位销售经理使用一个带有鸽笼式格架的书柜,这些格架类似于数据块。

每个格架都有描述出售给客户的衬衫的收据(行),按发货日期排序。在这个类比中,区域映射就像一叠索引卡片。每张卡片对应一个区域(连续的范围)的格架,例如格架 1-10。对于每个区域,卡片列出了该区域中存储的收据的最小和最大发货日期。

当有人想知道哪些衬衫在特定日期发货时,经理翻阅卡片,直到找到包含请求日期的日期范围,记下格架区域,然后只在该区域的格架中搜索请求的收据。通过这种方式,经理避免了搜索书柜中的每个格架来查找收据。

Zone Maps(区域映射)

区域映射是一种独立的访问结构,它将数据块划分为区域。Oracle AI 数据库将每个区域映射实现为一种物化视图。

与索引一样,区域映射可以降低表扫描的 I/O 和 CPU 成本。当 SQL 语句包含对区域映射中的列的谓词时,数据库会将谓词值与每个区域中存储的最小和最大表列值进行比较,以确定在 SQL 执行期间要读取哪些区域。

基本区域映射在单个表上定义,并维护该表某些列的最小值和最大值。连接区域映射在具有一个或多个其他表的外连接的表上定义,并维护其他表中某些列的最小值和最大值。Oracle AI 数据库自动维护这两种类型的区域映射。

一个表上最多可以存在一个区域映射。对于分区表,所有分区和子分区存在一个区域映射。分区表的区域映射还会跟踪每个区域、每个分区和每个子分区的最小值和最大值。如果表与维度表具有外连接,则区域映射定义可以包含维度列的最小值和最大值。

注意:您可以创建仅包含分区或子分区级别区域的区域映射。创建这样的区域映射可以扩展分区修剪能力,超越分区元数据。

相关参考:
《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解区域映射的概述

Zone Map Creation(区域映射创建)

基本区域映射可以手动或自动创建。

  • Manual Zone Maps(手动区域映射)
    您可以使用 DDL 语句创建、删除和维护区域映射。

  • Automatic Zone Maps(自动区域映射)
    Oracle AI 数据库可以自动创建基本区域映射。这些被称为自动区域映射。

Manual Zone Maps(手动区域映射)

您可以使用 DDL 语句创建、删除和维护区域映射。

每当您在 CREATE TABLE 或 ALTER TABLE 语句中指定 CLUSTERING 子句时,数据库会自动在指定的聚簇列上创建一个区域映射。区域映射将列的最小值和最大值与属性聚簇表中的连续数据块关联起来。属性聚簇表使用区域映射来执行 I/O 减少。

您也可以通过使用 CREATE MATERIALIZED ZONEMAP 语句显式创建区域映射。在这种情况下,您可以创建用于属性聚簇或不用于属性聚簇的区域映射。例如,您可以在行自然按一组列排序的表上创建区域映射,例如其交易按时间排序的股票交易表。

相关参考:

  • “Overview of Materialized Views(物化视图概述)”
  • 《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解有关如何创建区域映射的更多信息
Automatic Zone Maps(自动区域映射)

Oracle AI 数据库可以自动创建基本区域映射。这些被称为自动区域映射。

Oracle AI 数据库可以自动为分区表和非分区表创建基本区域映射。后台进程自动维护以这种方式创建的区域映射。

使用 DBMS_AUTO_ZONEMAP 过程启用自动区域映射:

EXEC DBMS_AUTO_ZONEMAP.CONFIGURE('AUTO_ZONEMAP_MODE','ON')

相关参考:

  • 《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解有关使用 DBMS_AUTO_ZONEMAP 包管理自动区域映射的更多信息
  • 《Oracle AI Database PL/SQL Packages and Types Reference》(《Oracle AI 数据库 PL/SQL 包和类型参考》):了解有关 DBMS_AUTO_ZONEMAP 包的更多信息
  • 《Oracle AI Database Licensing Information User Manual》(《Oracle AI 数据库许可信息用户手册》):了解有关不同版本和服务支持哪些功能的详细信息
How a Zone Map Works: Example(区域映射的工作原理:示例)

此示例说明区域映射如何在其谓词包含常量的查询中修剪数据。

假设您创建以下 lineitem 表:

CREATE TABLE lineitem 
  ( orderkey      NUMBER        , 
    shipdate      DATE          ,
    receiptdate   DATE          ,
    destination   VARCHAR2(50)  ,
    quantity      NUMBER        );

lineitem 表包含 4 个数据块,每个块有 2 行。表 4-4 显示了该表的 8 行。

Table 4-4 Data Blocks for lineitem Table(表4-4 lineitem 表的数据块)

块(Block) orderkey shipdate receiptdate destination quantity
1 1 1-1-2014 1-10-2014 San_Fran 100
1 2 1-2-2014 1-10-2014 San_Fran 200
2 3 1-3-2014 1-9-2014 San_Fran 100
2 4 1-5-2014 1-10-2014 San_Diego 100
3 5 1-10-2014 1-15-2014 San_Fran 100
3 6 1-12-2014 1-16-2014 San_Fran 200
4 7 1-13-2014 1-20-2014 San_Fran 100
4 8 1-15-2014 1-30-2014 San_Jose 100

您可以使用 CREATE MATERIALIZED ZONEMAP 语句在 lineitem 表上创建一个区域映射。每个区域包含 2 个块,并存储 orderkey、shipdate 和 receiptdate 列的最小值和最大值。表 4-5 显示了该区域映射。

Table 4-5 Zone Map for lineitem Table(表4-5 lineitem 表的区域映射)

块范围(Block Range) min orderkey max orderkey min shipdate max shipdate min receiptdate max receiptdate
1-2 1 4 1-1-2014 1-5-2014 1-9-2014 1-10-2014

Table 4-5 (Cont.) Zone Map for lineitem Table(表4-5 (续) lineitem 表的区域映射)

块范围(Block Range) min orderkey max orderkey min shipdate max shipdate min receiptdate max receiptdate
3-4 5 8 1-10-2014 1-15-2014 1-15-2014 1-30-2014

当您执行以下查询时,数据库可以读取区域映射,然后仅扫描块 1 和 2,从而跳过块 3 和 4,因为日期 1-3-2014 在最小日期和最大日期之间:

SELECT * FROM lineitem WHERE shipdate = '1-3-2014';

相关参考:

  • 《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解如何使用区域映射
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE MATERIALIZED ZONEMAP 语句的语法和语义

Attribute-Clustered Tables with Linear Ordering(具有线性排序的属性聚簇表)

表的线性排序方案根据用户指定的属性按特定顺序将行划分为多个范围。Oracle AI 数据库支持对通过主键-外键关系连接的单个或多个表进行线性排序。

例如,sales 表将 cust_id 和 prod_id 列划分为多个范围,然后在磁盘上将这些范围聚簇在一起。当您为表指定 BY LINEAR ORDER 指令时,如果谓词指定了指令中的前缀列或所有列,则可以显著减少 I/O。

假设对 sales 的查询经常指定客户 ID,或者同时指定客户 ID 和产品 ID。您可以创建一个属性聚簇表,以便此类查询受益于 I/O 减少:

CREATE TABLE sales
(
   prod_id     NOT NULL NUMBER
,  cust_id     NOT NULL NUMBER
,  amount_sold NUMBER(10,2) ...
)
CLUSTERING 
  BY LINEAR ORDER (cust_id, prod_id)
  YES ON LOAD YES ON DATA MOVEMENT
  WITH MATERIALIZED ZONEMAP;

同时限定 cust_id 和 prod_id 两列,或者限定前缀 cust_id 的查询会经历 I/O 减少。仅限定 prod_id 的查询不会显著减少 I/O,因为 prod_id 是 BY LINEAR ORDER 子句的后缀。以下示例显示了数据库如何在表扫描期间减少 I/O。

示例 4-9 仅指定 cust_id(Example 4-9 Specifying Only cust_id)

应用程序发出以下查询:

SELECT * FROM sales WHERE cust_id = 100;

因为 sales 表是一个 BY LINEAR ORDER 簇,数据库只需读取包含 cust_id 值 100 的区域。

示例 4-10 指定 prod_id 和 cust_id(Example 4-10 Specifying prod_id and cust_id)

应用程序发出以下查询:

SELECT * FROM sales WHERE cust_id = 100 AND prod_id = 2300;

因为 sales 表是一个 BY LINEAR ORDER 簇,数据库只需读取包含 cust_id 值 100 和 prod_id 值 2300 的区域。

相关参考:

  • 《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解如何使用线性排序聚簇表
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 BY LINEAR ORDER 子句的语法和语义

Attribute-Clustered Tables with Interleaved Ordering(具有交错排序的属性聚簇表)

交错排序使用了一种类似于 Z-order 的技术。

交错排序使数据库能够根据聚簇列中的任何谓词子集来修剪 I/O。交错排序对于数据仓库中的维度层次结构非常有用。

与具有线性排序的属性聚簇表一样,Oracle AI 数据库支持对通过主键-外键关系连接的单个或多个表进行交错排序。非属性聚簇表中的列必须通过外键链接并连接到属性聚簇表。

大型数据仓库通常以星型模式组织数据。维度表使用父子层次结构,并通过外键连接到事实表。以交错顺序聚簇事实表,使数据库能够使用特殊函数在表扫描期间跳过维度列中的值。

示例 4-11 交错排序示例(Example 4-11 Interleaved Ordering Example)

假设您的数据仓库包含一个 sales 事实表及其两个维度表:customers 和 products。大多数查询对 customers 表层次结构 (cust_state_province, cust_city) 和 products 层次结构 (prod_category, prod_subcategory) 具有谓词。您可以为 sales 表使用交错排序,如以下示例中的部分语句所示:

CREATE TABLE sales
(
   prod_id NUMBER NOT NULL
,  cust_id NUMBER NOT NULL
,  amount_sold NUMBER(10,2) ...
)
CLUSTERING sales
   JOIN products ON (sales.prod_id = products.prod_id)
   JOIN customers ON (sales.cust_id = customers.cust_id)
   BY INTERLEAVED ORDER
   (
     (  products.prod_category
     ,  products.prod_subcategory
     ),
     (  customers.cust_state_province
     ,  customers.cust_city
     )
   )
WITH MATERIALIZED ZONEMAP;

注意:BY INTERLEAVED ORDER 子句中指定的列不必在实际的维度表中,但它们必须通过主键-外键关系连接。

假设某个应用程序在连接中查询 sales、products 和 customers 表。该查询在谓词中指定了 customers.prod_category 和 customers_cust_state_province 列,如下所示:

SELECT cust_city, prod_sub_category, SUM(amount_sold)
FROM   sales, products, customers
WHERE  sales.prod_id = products.prod_id 
AND    sales.cust_id = customers.cust_id
AND    customers.prod_category = 'Boys' 
AND    customers.cust_state_province = 'England - Norfolk' 
GROUP BY cust_city, prod_sub_category;

在前面的查询中,prod_category 和 cust_state_province 列是 CREATE TABLE 示例中显示的聚簇定义的一部分。在扫描 sales 表期间,数据库可以查阅区域映射,并仅访问此区域中的 rowid。

相关参考:

  • “Overview of Dimensions(维度概述)”
  • 《Oracle AI Database Data Warehousing Guide》(《Oracle AI 数据库数据仓库指南》):了解如何使用交错排序聚簇表
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 BY INTERLEAVED ORDER 子句的语法和语义

Overview of Temporary Tables(临时表概述)

临时表保存仅在事务或会话期间存在的数据。

临时表中的数据是会话私有的。每个会话只能查看和修改自己的数据。

您可以创建全局临时表或私有临时表。下表显示了它们之间的基本区别。

Table 4-6 Temporary Table Characteristics(表4-6 临时表特性)

特性(Characteristic) 全局(Global) 私有(Private)
命名规则(Naming rules) 与永久表相同 必须以 ORA$PTT_ 为前缀
表定义的可见性(Visibility of table definition) 所有会话 仅创建该表的会话
表定义的存储(Storage of table definition) 磁盘 仅内存
类型(Types) 事务特定 (ON COMMIT DELETE ROWS) 或会话特定 (ON COMMIT PRESERVE ROWS) 事务特定 (ON COMMIT DROP DEFINITION) 或会话特定 (ON COMMIT PRESERVE DEFINITION)

第三种类型的临时表,称为游标持续时间临时表,由数据库为某些类型的查询自动创建。

  • Purpose of Temporary Tables(临时表的目的)
    临时表在必须缓冲结果集的应用程序中非常有用。

  • Segment Allocation in Temporary Tables(临时表中的段分配)
    与永久表一样,全局临时表是在数据字典中静态定义的持久对象。对于私有临时表,元数据仅存在于内存中,但可以驻留在磁盘上的临时表空间中。

  • Temporary Table Creation(临时表的创建)
    CREATE ... TEMPORARY TABLE 语句创建一个临时表。

相关参考:
《Oracle AI Database SQL Tuning Guide》(《Oracle AI 数据库 SQL 调优指南》):了解有关游标持续时间临时表的更多信息

Purpose of Temporary Tables(临时表的目的)

临时表在必须缓冲结果集的应用程序中非常有用。

例如,一个选课应用程序允许大学生创建可选的学期课程表。全局临时表中的一行代表每个课程表。在会话期间,课程表数据是私有的。当学生选择一个课程表时,应用程序会将所选课程表的行移动到永久表中。在会话结束时,数据库会自动删除全局临时表中的课程表数据。

私有临时表对于动态报告应用程序非常有用。例如,客户资源管理(CRM)应用程序可能无限期地以同一用户身份连接,同时有多个会话处于活动状态。每个会话为每个新事务创建一个名为 ORA$PTT_crm 的私有临时表。应用程序可以在每个会话中使用相同的表名,但更改定义。数据和定义仅对会话可见。表定义会一直存在,直到事务结束或表被手动删除。

Segment Allocation in Temporary Tables(临时表中的段分配)

与永久表一样,全局临时表是在数据字典中静态定义的持久对象。对于私有临时表,元数据仅存在于内存中,但可以驻留在磁盘上的临时表空间中。

对于全局和私有临时表,数据库会在会话首次插入数据时分配临时段。在会话中加载数据之前,该表显示为空。对于事务特定的临时表,数据库会在事务结束时释放临时段。对于会话特定的临时表,数据库会在会话结束时释放临时段。

相关参考:
“Temporary Segments(临时段)”

Temporary Table Creation(临时表的创建)

CREATE ... TEMPORARY TABLE 语句创建一个临时表。

指定 GLOBAL TEMPORARY TABLEPRIVATE TEMPORARY TABLE。在这两种情况下,ON COMMIT 子句指定表数据是事务特定的(默认)还是会话特定的。您是为数据库本身创建临时表,而不是为每个 PL/SQL 存储过程创建。

您可以使用 CREATE INDEX 语句为全局(而非私有)临时表创建索引。这些索引也是临时的。索引中的数据具有与临时表中数据相同的会话或事务作用域。您还可以在全局临时表上创建视图或触发器。

相关参考:

  • “Overview of Views(视图概述)”
  • “Overview of Triggers(触发器概述)”
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何创建和管理临时表
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE ... TEMPORARY TABLE 的语法和语义

Overview of External Tables(外部表概述)

外部表访问外部源中的数据,就像这些数据位于数据库的表中一样。

数据可以是为其提供了访问驱动程序的任何格式。您可以使用 SQL(串行或并行)、PL/SQL 和 Java 来查询外部表。

  • Purpose of External Tables(外部表的目的)
    当 Oracle 数据库应用程序必须访问非关系数据时,外部表非常有用。

  • Data in Object Stores(对象存储中的数据)
    外部表可用于访问对象存储中的数据。

  • External Table Access Drivers(外部表访问驱动程序)
    访问驱动程序是一种 API,用于为数据库解释外部数据。访问驱动程序在数据库内部运行,数据库使用该驱动程序读取外部表中的数据。访问驱动程序和外部表层负责对数据文件中的数据执行所需的转换,使其与外部表定义相匹配。

  • External Table Creation(外部表的创建)
    在内部,创建外部表意味着在数据字典中创建元数据。与普通表不同,外部表不描述存储在数据库中的数据,也不描述数据在外部是如何存储的。相反,外部表元数据描述了外表层必须如何向数据库呈现数据。

  • Automatic Caching of External Table Data(外部表数据的自动缓存)
    来自外部表的数据会被透明地缓存,以提高查询性能。

Purpose of External Tables(外部表的目的)

当 Oracle 数据库应用程序必须访问非关系数据时,外部表非常有用。

例如,一个基于 SQL 的应用程序可能需要访问一个文本文件,其记录格式如下:

100,Steven,King,SKING,515.123.4567,17-JUN-03,AD_PRES,31944,150,90
101,Neena,Kochhar,NKOCHHAR,515.123.4568,21-SEP-05,AD_VP,17000,100,90 
102,Lex,De Haan,LDEHAAN,515.123.4569,13-JAN-01,AD_VP,17000,100,90

您可以创建一个外部表,将文本文件复制到外部表定义中指定的位置,然后使用 SQL 查询文本文件中的记录。类似地,您可以使用外部表提供对 JSON 文档或 LOB 的只读访问。

在数据仓库环境中,外部表对于执行提取、转换和加载(ETL)任务非常有价值。例如,外部表使您能够将数据加载阶段与转换阶段进行管道化。此技术无需在数据库内部暂存数据,为数据库内部的进一步处理做准备。

您可以在虚拟列或非虚拟列上对外部表进行分区。此外,您可以创建一个混合分区表,其中一些分区是内部的,一些是外部的。与内部分区一样,外部分区受益于性能增强,例如分区修剪和分区级连接。例如,您可以使用分区外部表来分析存储在 Hadoop 分布式文件系统(HDFS)或 NoSQL 数据库中的大量非关系数据。

相关参考:
“Partitioned Tables(分区表)”

Data in Object Stores(对象存储中的数据)

外部表可用于访问对象存储中的数据。

除了支持访问驻留在操作系统文件和大数据源中的外部数据外,Oracle 还支持访问对象存储中的外部数据。对象存储在云中很常见,它提供了一种扁平架构,通过将各个对象(任何类型的具有元数据的非结构化数据)分组在简单的容器中来进行管理。尽管对象存储主要是一种云中的数据存储架构,但它也可用作本地存储硬件。

您可以通过使用 DBMS_CLOUD 包或通过手动定义外部表来访问对象存储中的数据。Oracle 强烈建议使用 DBMS_CLOUD 包,因为它提供了额外的功能,并且与 Oracle Autonomous Database 完全兼容。

External Table Access Drivers(外部表访问驱动程序)

访问驱动程序是一种 API,用于为数据库解释外部数据。访问驱动程序在数据库内部运行,数据库使用该驱动程序读取外部表中的数据。访问驱动程序和外部表层负责对数据文件中的数据执行所需的转换,使其与外部表定义相匹配。

下图表示对外部数据的 SQL 访问。

Figure 4-11 External Tables(图4-11 外部表)

Oracle 为外部表提供以下访问驱动程序:

  • ORACLE_LOADER(默认)
    允许访问使用 SQL*Loader 支持的大多数格式的外部文件。您不能使用 ORACLE_LOADER 驱动程序创建、更新或追加外部文件。

  • ORACLE_DATAPUMP
    使您能够卸载或加载外部数据。卸载操作从数据库中读取数据,并将数据插入到由一个或多个外部文件表示的外部表中。创建外部文件后,数据库无法更新数据或向其中追加数据。加载操作读取外部表并将其数据加载到数据库中。

  • ORACLE_HDFS
    允许提取存储在 Hadoop 分布式文件系统(HDFS)中的数据。

  • ORACLE_HIVE
    允许访问存储在 Apache Hive 数据库中的数据。源数据可以存储在 HDFS、HBase、Cassandra 或其他系统中。与其他访问驱动程序不同,您不能指定位置,因为 ORACLE_HIVE 从外部元数据存储获取位置信息。

  • ORACLE_BIGDATA
    允许以只读方式访问以结构化和非结构化格式存储的数据,包括 Apache Parquet、Apache Avro、Apache ORC、Apache Iceberg、Linux 开放项目 Delta Sharing 协议以及文本格式。您也可以使用此驱动程序查询本地数据,这对于测试和较小的数据集非常有用。

External Table Creation(外部表的创建)

在内部,创建外部表意味着在数据字典中创建元数据。与普通表不同,外部表不描述存储在数据库中的数据,也不描述数据在外部是如何存储的。相反,外部表元数据描述了外表层必须如何向数据库呈现数据。

CREATE TABLE ... ORGANIZATION EXTERNAL 语句有两个部分。外部表定义描述了列类型。此定义类似于一个视图,它使 SQL 能够查询外部数据,而无需将其加载到数据库中。该语句的第二部分将外部数据映射到列。

外部表是只读的,除非使用带有 ORACLE_DATAPUMP 访问驱动程序的 CREATE TABLE AS SELECT 创建。外部表的限制包括不支持索引列和列对象。

相关参考:

  • 《Oracle AI Database Utilities》(《Oracle AI 数据库实用程序》):了解有关外部表的信息
  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解有关管理外部表、外部连接和目录对象的信息
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解创建和查询外部表的信息

Automatic Caching of External Table Data(外部表数据的自动缓存)

来自外部表的数据会被透明地缓存,以提高查询性能。

完全或部分驻留在对象存储中的外部表的频繁访问数据会被自动缓存以提高性能。外部表数据的缓存不需要更改应用程序,因为它由 Oracle 数据库自动处理。

Overview of Blockchain Tables(区块链表概述)

区块链表是一种仅追加表,专为集中式区块链应用程序设计。

在 Oracle 区块链表中,对等方是信任数据库能够维护防篡改账本的数据库用户。该账本实现为区块链表,由应用程序定义和管理。现有应用程序可以防范欺诈,而无需新的基础设施或编程模型。尽管事务吞吐量低于标准表,但区块链表的性能优于去中心化区块链。

区块链表之所以是仅追加的,是因为唯一允许的 DML 是 INSERT 命令。该表不允许 UPDATE、DELETE、MERGE、TRUNCATE 和直接路径加载。数据库事务可以跨越区块链表和标准表。例如,单个事务可以将行插入到标准表和两个不同的区块链表中。

区块链表可用于保护闪回数据归档内容。这使您能够确定是否有人篡改了表的内容。可以将区块链日志历史表视为为跟踪用户表的更改维护一个加密安全的逻辑重做日志。

从版本 2 区块链表开始,您可以从区块链表中添加或删除用户列。不允许从版本 1 区块链表中添加或删除用户列。物理列和数据实际上并未删除,而是被标记为不可见。

  • Row Chains(行链)
    在区块链表中,行链是通过哈希方案链接在一起的一系列行。

  • Row Content(行内容)
    行内容是包含该行的列数据以及链中上一行的哈希值的连续字节序列。

  • User Interface for Blockchain Tables(区块链表的用户界面)
    与标准表一样,区块链表通过 SQL 创建,并支持标量数据类型、LOB、JSON 和分区。您还可以为区块链表创建索引和触发器。

Row Chains(行链)

在区块链表中,行链是通过哈希方案链接在一起的一系列行。

在版本 1 区块链表中,系统行链由数据库实例 ID 和链 ID 的唯一组合标识。从版本 2 区块链表开始,除了这两个标识符之外,还需要插入该行的数据库的全局唯一标识符。在版本 2 区块链表中,系统行链由可插入数据库全局唯一 ID、数据库实例 ID 和链 ID 的唯一组合标识。区块链表中的一行恰好属于一个系统行链。单个表支持多个系统行链。

注意:标准表中的链式行与区块链表中的行链是互不相关的。只有“链”这个词是相同的。

链中的每一行都有一个唯一的序列号。数据库使用对每个链的行进行 SHA2-512 哈希计算来对行进行排序。每个插入行的哈希值是从插入行的行内容派生而来的,其中包括链中先前插入行的哈希值。

虽然区块链表中的每一行都恰好属于一个系统链,但它也可以属于一个用户链,该用户链基于创建区块链表时指定的一组用户列的值。

Row Content(行内容)

行内容是包含该行的列数据以及链中上一行的哈希值的连续字节序列。

创建区块链表时,数据库会创建几个隐藏列。例如,您可以创建具有 bank 和 deposit 列的区块链表 bank_ledger:

CREATE BLOCKCHAIN TABLE bank_ledger (bank VARCHAR2 (128), deposit NUMBER)
  NO DROP UNTIL 31 DAYS IDLE 
  NO DELETE UNTIL 31 DAYS AFTER INSERT
  HASHING USING "SHA2_512" VERSION "v1";

数据库自动创建带有前缀 ORABCTAB 的隐藏列:ORABCTAB_INST_ID、ORABCTABCHAINID、ORABCTAB_CHAIN_IDORABCTABCHAINID、ORABCTAB_SEQ_NUM$ 等。这些隐藏列(大多数您无法更改或管理)实现了防篡改算法。该算法通过在提交时按特定顺序获取唯一的、表级链锁来避免死锁。

注意:区块链表的行内容存储在标准数据块中。在此版本的 Oracle AI 数据库中,区块链表不支持表簇。

实例 ID、链 ID 和序列号唯一标识一行。从版本 2 区块链表开始,除了这三个值之外,还需要插入该行的数据库的全局唯一标识符。每行都有一个与平台无关的 SHA2-512 哈希值,该哈希值存储在隐藏列 ORABCTAB_HASH$ 中。该哈希值基于插入行的内容以及链中上一行的哈希值。

行中列值的数据格式由列元数据和内容中的字节组成。列元数据是一个 20 字节的结构,描述了诸如表中的位置、数据类型、空状态和字节长度等特征。列内容是表示行中值的字节集合。例如,值 Chase 的 ASCII 表示为 43 68 61 73 65。您可以在 SQL 中使用 DUMP 函数来获取列元数据和内容。

用于哈希计算的行内容包括来自多个列的列数据格式:链中前一行的哈希值、用户定义的列以及固定数量的隐藏列。

相关行的插入顺序(称为行版本)可以由系统跟踪,并通过指定一组定义行版本的列来记录。此外,如果指定了行版本,则会自动创建并维护一个视图,该视图显示用户指定的列集中每个值组合的最后插入行。视图名称使用命名约定 Blockchain_Table_Name _LAST$。

在许多情况下,行需要额外或替代地由最终用户的委托人来签名。一个例子是银行经理对最终用户插入的行进行签名。委托人签名者是另一个数据库用户,他们可以在基于行的系统加密哈希计算的行上添加自己的签名。一行可以由最终用户签名,也可以由委托人签名,或者同时由两者签名。只有当签名可以使用委托人的证书进行验证,并且委托人的证书记录在数据库字典表中时,委托人的签名才会被接受。

当一行由最终用户或委托人签名时,用户可能希望为该行获取一个副署签名。副署签名可以被认为是专门针对已由最终用户或委托人签名的行的区块链表摘要。当一行被副署时,副署签名会返回给行签名者,并同时保存在该行中。在该行上请求副署签名的用户可以将此信息保存在单独的数据存储中,以备不时之需(非否认目的)。

User Interface for Blockchain Tables(区块链表的用户界面)

与标准表一样,区块链表通过 SQL 创建,并支持标量数据类型、LOB、JSON 和分区。您还可以为区块链表创建索引和触发器。

要创建区块链表,请使用 CREATE BLOCKCHAIN TABLE 语句。区块链表有一个由 NO DROP UNTIL n DAYS IDLE 子句指定的保留期。您可以使用 DROP TABLE 删除该表。

Oracle 区块链表支持以下接口:

  • DBMS_BLOCKCHAIN_TABLE 包使您能够对表行执行各种操作。例如,要对先前插入的行的内容应用签名,请使用 SIGN_ROW 过程。要验证行是否未被篡改,请使用 VERIFY_ROWS。要在保留期(由 NO DELETE 子句指定)过去后删除行,请使用 DELETE_EXPIRED_ROWS

  • DBA_BLOCKCHAIN_TABLES 视图显示表元数据,例如行保留期、允许删除表之前的非活动期以及哈希算法。

注意

  • 《Oracle AI Database Administrator’s Guide》(《Oracle AI 数据库管理员指南》):了解如何管理区块链表
  • 《Oracle AI Database PL/SQL Packages and Types Reference》(《Oracle AI 数据库 PL/SQL 包和类型参考》):了解 DBMS_BLOCKCHAIN_TABLE 包
  • 《Oracle AI Database Reference》(《Oracle AI 数据库参考》):了解 DBA_BLOCKCHAIN_TABLES 视图

Overview of Immutable Tables(不可变表概述)

不可变表是仅追加表,可防止内部人员的未经授权的数据修改以及因人为错误导致的意外数据修改。

未经授权的修改可能是由拥有内部凭证的受损或恶意员工尝试的。

可以向不可变表添加新行,但不能修改现有行。您必须为不可变表和不可变表中的行指定保留期。行在指定的行保留期之后变为过时。只能从不可变表中删除过时的行。

不可变表包含系统生成的隐藏列。这些列与区块链表的列相同。当插入一行时,会为 ORABCTAB_CREATION_TIME$ 和 ORABCTAB_USER_NUMBER$ 列设置非 NULL 值。除 V1 不可变表外,会为 ORABCTAB_PDB_GUID$ 列设置非 NULL 值。如果不可变表是使用行版本创建的,则会为 ORABCTAB_ROW_VERSION$ 和 ORABCTAB_LAST_ROW_VERSION_NUMBER$ 列设置非 NULL 值。其余系统生成的隐藏列的值设置为 NULL。

使用不可变表无需更改现有应用程序。

Overview of Object Tables(对象表概述)

对象表是一种特殊的表,其中每一行代表一个对象。

Oracle 对象类型是一种具有名称、属性和方法的用户定义类型。对象类型使得将现实世界实体(如客户和采购订单)建模为数据库中的对象成为可能。

对象类型定义了逻辑结构,但不创建存储。以下示例创建了一个名为 department_typ 的对象类型:

CREATE TYPE department_typ AS OBJECT
   ( d_name     VARCHAR2(100),
     d_address  VARCHAR2(200) );
/

以下示例创建了对象类型 department_typ 的对象表 departments_obj_t,然后将一行插入到该表中。departments_obj_t 表的属性(列)源自对象类型的定义。

CREATE TABLE departments_obj_t OF department_typ;
INSERT INTO departments_obj_t VALUES ('hr', '10 Main St, Sometown, CA');

与关系列一样,对象表可以只包含一种事物的行,即与该表声明的类型相同的对象实例。默认情况下,对象表中的每个行对象都有一个关联的逻辑对象标识符(OID),该标识符在对象表中唯一标识它。对象表的 OID 列是一个隐藏列。

相关参考:

  • 《Oracle AI Database Object-Relational Developer’s Guide》(《Oracle AI 数据库对象关系开发人员指南》):了解 Oracle AI 数据库中的对象关系功能
  • 《Oracle AI Database SQL Language Reference》(《Oracle AI 数据库 SQL 语言参考》):了解 CREATE TYPE 的语法和语义
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐