Oracle 分区表设计详解

Oracle 分区表设计详解

适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

分区表将大表分解为更小、可管理的部分[1]:

优势

  • 性能(分区裁剪)
  • 管理(独立操作)
  • 可用性(部分故障)
  • 维护(归档)

详细见:Oracle 分区表设计


2. 分区类型

2.1 Range

CREATE TABLE sales (
  id NUMBER,
  sale_date DATE,
  amount NUMBER
)
PARTITION BY RANGE (sale_date) (
  PARTITION p2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD')),
  PARTITION p2025 VALUES LESS THAN (TO_DATE('2026-01-01', 'YYYY-MM-DD')),
  PARTITION p2026 VALUES LESS THAN (TO_DATE('2027-01-01', 'YYYY-MM-DD')),
  PARTITION pmax VALUES LESS THAN (MAXVALUE)
);

2.2 List

CREATE TABLE customers (
  id NUMBER,
  region VARCHAR2(20)
)
PARTITION BY LIST (region) (
  PARTITION p_east VALUES ('NY', 'Boston', 'Miami'),
  PARTITION p_west VALUES ('LA', 'SF', 'Seattle'),
  PARTITION p_central VALUES ('Chicago', 'Dallas'),
  PARTITION p_other VALUES (DEFAULT)
);

2.3 Hash

CREATE TABLE orders (
  id NUMBER,
  customer_id NUMBER
)
PARTITION BY HASH (customer_id) PARTITIONS 8;

2.4 Composite

CREATE TABLE sales (
  id NUMBER,
  sale_date DATE,
  region VARCHAR2(20)
)
PARTITION BY RANGE (sale_date)
  SUBPARTITION BY LIST (region)
    SUBPARTITION TEMPLATE (
      SUBPARTITION east VALUES ('NY', 'Boston'),
      SUBPARTITION west VALUES ('LA', 'SF'),
      SUBPARTITION other VALUES (DEFAULT)
    ) (
  PARTITION p2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD')),
  PARTITION p2025 VALUES LESS THAN (TO_DATE('2026-01-01', 'YYYY-MM-DD'))
);

2.5 Interval(11g+)

CREATE TABLE sales (
  id NUMBER,
  sale_date DATE,
  amount NUMBER
)
PARTITION BY RANGE (sale_date)
INTERVAL 'NUMTOYMINTERVAL(1, ''MONTH'')' (
  PARTITION p0 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD'))
);

2.6 Reference

CREATE TABLE orders (
  order_id NUMBER PRIMARY KEY,
  customer_id NUMBER,
  order_date DATE
)
PARTITION BY HASH (customer_id) PARTITIONS 4;

CREATE TABLE order_items (
  item_id NUMBER,
  order_id NUMBER,
  product_id NUMBER,
  CONSTRAINT fk_oi_order FOREIGN KEY (order_id) REFERENCES orders
)
PARTITION BY REFERENCE (fk_oi_order);

2.7 System

CREATE TABLE t (id NUMBER, name VARCHAR2(100))
PARTITION BY SYSTEM (
  PARTITION p1 TABLESPACE users,
  PARTITION p2 TABLESPACE users
);

INSERT INTO t PARTITION (p1) VALUES (1, 'A');

3. 选择策略

3.1 时间

- Range(日期)
- Interval(自动)
- DW / 日志

3.2 区域

- List
- 业务隔离

3.3 均匀

- Hash
- 任意列
- 负载均衡

3.4 多维

- Composite
- Range + List / Hash

4. 分区键

4.1 原则

- 查询常用
- 等值 / 范围
- 高基数(Hash)

4.2 限制

- 单列或多列
- 不能是 LONG
- 不能是 ROWID
- 限制类型

5. 索引

5.1 本地索引

CREATE INDEX idx_sales_date ON sales(sale_date) LOCAL;

5.2 全局索引

CREATE INDEX idx_sales_cust ON sales(customer_id) GLOBAL;

5.3 全局分区

CREATE INDEX idx_sales_cust ON sales(customer_id) GLOBAL
  PARTITION BY HASH (customer_id) PARTITIONS 4;

详细见:Oracle 索引类型与应用


6. 操作

6.1 添加分区

ALTER TABLE sales ADD PARTITION p2027 VALUES LESS THAN (TO_DATE('2028-01-01', 'YYYY-MM-DD'));

6.2 删除分区

ALTER TABLE sales DROP PARTITION p2024;

6.3 截断

ALTER TABLE sales TRUNCATE PARTITION p2024;

6.4 合并

ALTER TABLE sales MERGE PARTITIONS p2024, p2025 INTO PARTITION p2024_2025;

6.5 拆分

ALTER TABLE sales SPLIT PARTITION pmax AT (TO_DATE('2028-01-01', 'YYYY-MM-DD'))
  INTO (PARTITION p2027, PARTITION pmax);

6.6 交换

-- 分区 ↔ 表
CREATE TABLE sales_2024 AS SELECT * FROM sales WHERE 1=0;
ALTER TABLE sales EXCHANGE PARTITION p2024 WITH TABLE sales_2024;

6.7 移动

ALTER TABLE sales MOVE PARTITION p2024 TABLESPACE users COMPRESS;

6.8 重命名

ALTER TABLE sales RENAME PARTITION p2024 TO p_old;

7. 分区裁剪

7.1 静态

SELECT * FROM sales WHERE sale_date = DATE '2025-07-21';
-- 仅扫 p2025

7.2 动态

SELECT * FROM sales WHERE sale_date = :date;
-- 运行时裁剪

7.3 验证

EXPLAIN PLAN FOR SELECT ...;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY));
-- PARTITION RANGE SINGLE

8. 智能分区连接

8.1 Partition Wise Join

SELECT * FROM sales s, customers c 
WHERE s.customer_id = c.id;
-- 分区并行

9. 维护

9.1 统计

EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'SALES', cascade => TRUE);

-- 分区级
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'SALES', 
  partname => 'P2025', cascade => TRUE);

-- 增量
EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'SALES', 
  'INCREMENTAL', 'TRUE');

9.2 备份

RMAN> BACKUP TABLESPACE users;
RMAN> BACKUP DATAFILE 5;

9.3 归档

-- 旧分区归档
ALTER TABLE sales EXCHANGE PARTITION p2020 WITH TABLE sales_2020_archive;
ALTER TABLE sales DROP PARTITION p2020;

详细见:Oracle 备份策略与最佳实践


10. 12c 新特性

10.1 Interval-Reference

-- 不支持

10.2 多列分区

PARTITION BY RANGE (a, b)

10.3 Partial Index

CREATE TABLE sales (...) PARTITION BY RANGE (sale_date) (
  PARTITION p2024 ... INDEXING OFF,
  PARTITION p2025 ... INDEXING ON
);

CREATE INDEX idx ON sales (...) LOCAL INDEXING PARTIAL;

10.4 Online

ALTER TABLE sales MOVE PARTITION p2024 ONLINE;

11. 查看

11.1 表

SELECT table_name, partitioning_type, partition_count 
FROM user_part_tables;

11.2 分区

SELECT table_name, partition_name, tablespace_name, num_rows 
FROM user_tab_partitions;

11.3 子分区

SELECT * FROM user_tab_subpartitions;

11.4 键

SELECT name, column_name, column_position FROM user_part_key_columns;

12. 性能

12.1 分区裁剪

- WHERE 分区键
- 减少扫描

12.2 并行

ALTER TABLE sales PARALLEL 4;
SELECT /*+ PARALLEL(s 4) */ * FROM sales s WHERE ...;

12.3 索引

- 本地索引优先
- 维护成本低

13. 常见坑与排错

13.1 全局索引失效

ALTER TABLE sales DROP PARTITION p2024;
-- 全局索引失效
ALTER INDEX idx_sales_cust REBUILD;
-- 或 UPDATE INDEXES
ALTER TABLE sales DROP PARTITION p2024 UPDATE INDEXES;

13.2 分区键选择不当

- 无裁剪
- 性能差
- 重新选择

13.3 分区数过多

- 管理
- 限制
- 数量合理

14. 最佳实践

  1. 大表分区:> 10GB
  2. 时间分区:Range / Interval
  3. Hash 均匀:负载
  4. 本地索引:维护
  5. 分区裁剪:查询
  6. 增量统计:性能
  7. 归档:空间
  8. Online 操作:业务
  9. Partial Index:12c+
  10. 监控:使用

15. 参考资料

[1] Oracle Database Administrator’s Guide 19c, “Partitioning” https://docs.oracle.com/en/database/oracle/oracle-database/19/vldbg/