Skip to content

Oracle 数据库与表

Oracle 数据库是一个复杂的系统,由多个层次的对象组成。理解数据库和表的结构对于 DBA 进行日常维护、性能调优和数据管理至关重要。

数据库架构

传统数据库架构(Oracle 11g 及之前)

  • 数据库(Database):包含数据文件、控制文件、redo log 文件等物理文件
  • 实例(Instance):由内存结构(SGA)和后台进程组成
  • 表空间(Tablespace):数据库的逻辑存储单元,包含一个或多个数据文件
  • 段(Segment):表、索引等对象的存储空间
  • 区(Extent):段的基本存储单位,由多个连续的数据块组成
  • 块(Block):Oracle 存储的最小单位,对应磁盘上的物理块

多租户架构(Oracle 12c 及以上)

  • CDB(容器数据库):包含根容器(CDB$ROOT)、种子容器(PDB$SEED)和一个或多个 PDB
  • PDB(可插拔数据库):独立的数据库环境,可以像传统数据库一样使用
  • CDB$ROOT:存储 CDB 级别的元数据和公共用户
  • PDB$SEED:用于创建新 PDB 的模板

表空间管理

表空间类型

  • 系统表空间(SYSTEM):存储数据字典和系统元数据
  • SYSAUX 表空间:辅助系统表空间,存储 Oracle 组件数据
  • 用户表空间:存储用户数据和对象
  • 临时表空间:存储临时数据,如排序结果
  • 撤销表空间(UNDO):存储撤销数据,用于事务回滚和一致性读

表空间创建与管理

  • 创建表空间

    sql
    -- 创建永久表空间
    CREATE TABLESPACE users 
    DATAFILE '+DATA' SIZE 100M 
    AUTOEXTEND ON NEXT 10M MAXSIZE 1000M 
    EXTENT MANAGEMENT LOCAL 
    SEGMENT SPACE MANAGEMENT AUTO;
    
    -- 创建临时表空间
    CREATE TEMPORARY TABLESPACE temp 
    TEMPFILE '+DATA' SIZE 50M 
    AUTOEXTEND ON NEXT 10M MAXSIZE 200M;
    
    -- 创建撤销表空间
    CREATE UNDO TABLESPACE undo 
    DATAFILE '+DATA' SIZE 100M 
    AUTOEXTEND ON NEXT 20M MAXSIZE 500M;
  • 表空间监控

    sql
    -- 查看表空间使用情况
    SELECT tablespace_name, 
           ROUND(total_space, 2) AS total_gb, 
           ROUND(used_space, 2) AS used_gb, 
           ROUND(free_space, 2) AS free_gb, 
           ROUND((used_space/total_space)*100, 2) AS used_percent
    FROM (
      SELECT tablespace_name, 
             SUM(bytes)/1024/1024/1024 AS total_space,
             SUM(bytes - NVL(free_bytes, 0))/1024/1024/1024 AS used_space,
             SUM(NVL(free_bytes, 0))/1024/1024/1024 AS free_space
      FROM (
        SELECT tablespace_name, bytes, 0 AS free_bytes
        FROM dba_data_files
        UNION ALL
        SELECT tablespace_name, 0 AS bytes, bytes AS free_bytes
        FROM dba_free_space
      )
      GROUP BY tablespace_name
    )
    ORDER BY used_percent DESC;
  • 表空间维护

    sql
    -- 扩展表空间数据文件
    ALTER DATABASE DATAFILE '+DATA/orcl/datafile/users.259.1012345678' RESIZE 200M;
    
    -- 添加数据文件
    ALTER TABLESPACE users ADD DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON;
    
    -- 切换撤销表空间
    ALTER SYSTEM SET undo_tablespace=undo2 SCOPE=BOTH;
    
    -- 删除表空间
    DROP TABLESPACE old_users INCLUDING CONTENTS AND DATAFILES;

表设计

数据类型选择

数据类型用途版本差异最佳实践
VARCHAR2可变长字符数据Oracle 12c+ 支持最大 32767 字节优先使用 VARCHAR2 而非 CHAR
NUMBER数值数据所有版本支持根据实际数值范围选择精度和小数位
DATE日期和时间所有版本支持Oracle 11g 引入 TIMESTAMP 类型,更精确
TIMESTAMP带时区的日期时间Oracle 11g 引入存储精确时间时使用
CLOB大字符数据所有版本支持Oracle 12c+ 支持 SecureFiles LOB
BLOB二进制数据所有版本支持Oracle 12c+ 支持 SecureFiles LOB
JSONJSON 数据类型Oracle 19c 引入存储和查询 JSON 数据时使用

表创建与管理

  • 创建表

    sql
    CREATE TABLE employees (
      employee_id   NUMBER(6) PRIMARY KEY,
      first_name    VARCHAR2(20),
      last_name     VARCHAR2(25) NOT NULL,
      email         VARCHAR2(100) NOT NULL UNIQUE,
      phone_number  VARCHAR2(20),
      hire_date     DATE NOT NULL,
      job_id        VARCHAR2(10) NOT NULL,
      salary        NUMBER(8,2),
      commission_pct NUMBER(2,2),
      manager_id    NUMBER(6),
      department_id NUMBER(4)
    ) TABLESPACE users;
  • 分区表创建

    sql
    -- 按范围分区
    CREATE TABLE sales (
      sale_id      NUMBER PRIMARY KEY,
      sale_date    DATE NOT NULL,
      product_id   NUMBER NOT NULL,
      quantity     NUMBER NOT NULL,
      amount       NUMBER(10,2) NOT NULL
    )
    PARTITION BY RANGE (sale_date) (
      PARTITION sales_2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD')),
      PARTITION sales_2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD')),
      PARTITION sales_future VALUES LESS THAN (MAXVALUE)
    ) TABLESPACE users;
  • 临时表创建

    sql
    -- 会话级临时表
    CREATE GLOBAL TEMPORARY TABLE temp_sales (
      sale_id      NUMBER,
      sale_date    DATE,
      amount       NUMBER(10,2)
    ) ON COMMIT PRESERVE ROWS;
    
    -- 事务级临时表
    CREATE GLOBAL TEMPORARY TABLE temp_order (
      order_id     NUMBER,
      product_id   NUMBER,
      quantity     NUMBER
    ) ON COMMIT DELETE ROWS;

表维护

  • 表结构修改

    sql
    -- 添加列
    ALTER TABLE employees ADD (middle_name VARCHAR2(15));
    
    -- 修改列
    ALTER TABLE employees MODIFY (email VARCHAR2(150));
    
    -- 删除列
    ALTER TABLE employees DROP COLUMN middle_name;
    
    -- 添加约束
    ALTER TABLE employees ADD CONSTRAINT emp_dept_fk FOREIGN KEY (department_id) REFERENCES departments(department_id);
    
    -- 禁用约束
    ALTER TABLE employees DISABLE CONSTRAINT emp_dept_fk;
    
    -- 启用约束
    ALTER TABLE employees ENABLE CONSTRAINT emp_dept_fk;
  • 表空间迁移

    sql
    -- 迁移表到新表空间
    ALTER TABLE employees MOVE TABLESPACE new_users;
    
    -- 迁移索引到新表空间
    ALTER INDEX emp_pk REBUILD TABLESPACE new_indexes;
  • 表统计信息收集

    sql
    -- 收集表统计信息
    EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'HR', TABNAME => 'EMPLOYEES', CASCADE => TRUE);
    
    -- 收集架构统计信息
    EXEC DBMS_STATS.GATHER_SCHEMA_STATS(OWNNAME => 'HR');

多租户环境管理

PDB 创建与管理

  • 创建 PDB

    sql
    -- 从 PDB$SEED 创建
    CREATE PLUGGABLE DATABASE pdb1 ADMIN USER pdb_admin IDENTIFIED BY Password123
    FILE_NAME_CONVERT = ('+DATA/orcl/pdbseed/', '+DATA/orcl/pdb1/');
    
    -- 启动 PDB
    ALTER PLUGGABLE DATABASE pdb1 OPEN;
    
    -- 关闭 PDB
    ALTER PLUGGABLE DATABASE pdb1 CLOSE IMMEDIATE;
  • PDB 监控

    sql
    -- 查看 PDB 状态
    SELECT pdb_name, status FROM dba_pdbs;
    
    -- 查看 PDB 数据文件
    SELECT name FROM v$datafile WHERE con_id = 3;
    
    -- 切换到 PDB
    ALTER SESSION SET CONTAINER = pdb1;

CDB 与 PDB 资源管理

  • 设置 PDB 资源限制
    sql
    -- 创建资源计划
    BEGIN
      DBMS_RESOURCE_MANAGER_CREATE_PLAN(PLAN => 'PDB_PLAN', COMMENT => 'PDB Resource Plan');
    END;
    /
    
    -- 创建资源分配指令
    BEGIN
      DBMS_RESOURCE_MANAGER_CREATE_CONSUMER_GROUP(CONSUMER_GROUP => 'PDB_GROUP', COMMENT => 'PDB Consumer Group');
    END;
    /
    
    -- 分配资源
    BEGIN
      DBMS_RESOURCE_MANAGER_CREATE_PLAN_DIRECTIVE(
        PLAN => 'PDB_PLAN',
        GROUP_OR_SUBPLAN => 'PDB_GROUP',
        COMMENT => 'PDB Directive',
        CPU_P1 => 50,
        CPU_P2 => 30
      );
    END;
    /

表空间与表监控

关键监控指标

  • 表空间使用率 > 90% 时需要告警
  • 表空间自动扩展次数过多
  • 大表(> 100GB)的增长趋势
  • 临时表空间使用率
  • 撤销表空间大小和使用率

监控脚本示例

sql
-- 表空间使用率监控
SELECT tablespace_name,
       ROUND((used_space/total_space)*100, 2) AS used_percent,
       ROUND(total_space, 2) AS total_gb,
       ROUND(used_space, 2) AS used_gb
FROM (
  SELECT tablespace_name,
         SUM(bytes)/1024/1024/1024 AS total_space,
         SUM(bytes - NVL(free_bytes, 0))/1024/1024/1024 AS used_space
  FROM (
    SELECT tablespace_name, bytes, 0 AS free_bytes
    FROM dba_data_files
    UNION ALL
    SELECT tablespace_name, 0 AS bytes, bytes AS free_bytes
    FROM dba_free_space
  )
  GROUP BY tablespace_name
)
WHERE ROUND((used_space/total_space)*100, 2) > 80
ORDER BY used_percent DESC;

-- 大表监控
SELECT owner, table_name, ROUND(bytes/1024/1024/1024, 2) AS size_gb
FROM dba_segments
WHERE segment_type = 'TABLE'
AND bytes/1024/1024/1024 > 50
ORDER BY bytes DESC;

-- 临时表空间使用监控
SELECT tablespace_name, session_id, sql_id, ROUND(blocks*8/1024/1024, 2) AS mb_used
FROM v$tempseg_usage
ORDER BY mb_used DESC;

最佳实践

表空间设计最佳实践

  1. 分离系统和用户数据:将 SYSTEM、SYSAUX 与用户表空间分离
  2. 分离数据和索引:将表和索引存储在不同的表空间和磁盘上
  3. 使用本地管理表空间:Oracle 10g 及以上推荐使用本地管理表空间
  4. 使用自动段空间管理:提高空间利用率和性能
  5. 合理设置表空间大小:避免频繁自动扩展,建议初始大小足够大
  6. 为大表创建独立表空间:便于管理和性能调优

表设计最佳实践

  1. 选择合适的数据类型:根据实际数据选择最适合的数据类型
  2. 避免使用 CHAR 类型:优先使用 VARCHAR2,节省存储空间
  3. 使用 NUMBER 类型时指定精度:如 NUMBER(10,2) 而非 NUMBER
  4. 为大表创建分区:提高查询性能和管理效率
  5. 合理使用索引:避免过度索引,根据查询需求创建
  6. 使用约束确保数据完整性:主键、外键、唯一约束等
  7. 定期收集统计信息:确保优化器生成最佳执行计划

多租户环境最佳实践

  1. 合理规划 PDB 数量:根据服务器资源和业务需求规划
  2. 为每个 PDB 分配独立表空间:便于管理和资源隔离
  3. 使用资源计划管理 PDB 资源:避免个别 PDB 消耗过多资源
  4. 定期备份 PDB:可以单独备份和恢复 PDB
  5. 使用 PDB 快照:快速创建测试环境

版本差异

版本特性
Oracle 11g引入 SecureFiles LOB,增强分区表功能
Oracle 12c引入多租户架构(CDB/PDB),支持 VARCHAR2 最大 32767 字节
Oracle 18c增强多租户功能,引入 PDB 快照
Oracle 19c引入 JSON 数据类型,增强分区表功能
Oracle 23c增强 JSON 支持,引入向量数据库功能

常见问题(FAQ)

Q1: 如何查看表空间的使用情况?

A1: 使用以下查询查看表空间使用情况:

sql
SELECT tablespace_name, 
       ROUND(total_space, 2) AS total_gb, 
       ROUND(used_space, 2) AS used_gb, 
       ROUND(free_space, 2) AS free_gb, 
       ROUND((used_space/total_space)*100, 2) AS used_percent
FROM (
  SELECT tablespace_name, 
         SUM(bytes)/1024/1024/1024 AS total_space,
         SUM(bytes - NVL(free_bytes, 0))/1024/1024/1024 AS used_space,
         SUM(NVL(free_bytes, 0))/1024/1024/1024 AS free_space
  FROM (
    SELECT tablespace_name, bytes, 0 AS free_bytes
    FROM dba_data_files
    UNION ALL
    SELECT tablespace_name, 0 AS bytes, bytes AS free_bytes
    FROM dba_free_space
  )
  GROUP BY tablespace_name
);

Q2: 如何扩展表空间?

A2: 可以通过以下两种方式扩展表空间:

  1. 调整现有数据文件大小:
    sql
    ALTER DATABASE DATAFILE '+DATA/orcl/datafile/users.259.1012345678' RESIZE 200M;
  2. 添加新的数据文件:
    sql
    ALTER TABLESPACE users ADD DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON;

Q3: 如何创建分区表?

A3: 示例:

sql
CREATE TABLE sales (
  sale_id      NUMBER PRIMARY KEY,
  sale_date    DATE NOT NULL,
  product_id   NUMBER NOT NULL,
  quantity     NUMBER NOT NULL,
  amount       NUMBER(10,2) NOT NULL
)
PARTITION BY RANGE (sale_date) (
  PARTITION sales_2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD')),
  PARTITION sales_2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD')),
  PARTITION sales_future VALUES LESS THAN (MAXVALUE)
);

Q4: 如何在多租户环境中创建 PDB?

A4: 示例:

sql
CREATE PLUGGABLE DATABASE pdb1 ADMIN USER pdb_admin IDENTIFIED BY Password123
FILE_NAME_CONVERT = ('+DATA/orcl/pdbseed/', '+DATA/orcl/pdb1/');

Q5: 如何迁移表到新表空间?

A5: 示例:

sql
-- 迁移表
ALTER TABLE employees MOVE TABLESPACE new_users;

-- 迁移索引
ALTER INDEX emp_pk REBUILD TABLESPACE new_indexes;

Q6: 如何监控临时表空间使用?

A6: 示例:

sql
SELECT tablespace_name, session_id, sql_id, ROUND(blocks*8/1024/1024, 2) AS mb_used
FROM v$tempseg_usage
ORDER BY mb_used DESC;

相关命令速查

命令用途
CREATE TABLESPACE创建表空间
ALTER TABLESPACE修改表空间
DROP TABLESPACE删除表空间
CREATE TABLE创建表
ALTER TABLE修改表
DROP TABLE删除表
CREATE PLUGGABLE DATABASE创建 PDB
ALTER PLUGGABLE DATABASE修改 PDB
DROP PLUGGABLE DATABASE删除 PDB
DBMS_STATS.GATHER_TABLE_STATS收集表统计信息
SELECT * FROM dba_tablespaces查看表空间信息
SELECT * FROM dba_data_files查看数据文件信息
SELECT * FROM dba_tables查看表信息

总结

Oracle 数据库与表是数据库架构的核心组成部分,DBA 应该深入理解其结构和管理方法。合理的表空间设计、表设计和多租户环境管理对于数据库的稳定高效运行至关重要。DBA 应该根据实际业务需求和服务器资源,选择合适的设计方案,并定期进行监控和维护,以确保数据库的性能和可靠性。