Oracle 分区裁剪详解

Oracle 分区裁剪详解

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


1. 概述

分区裁剪(Partition Pruning)跳过不相关分区[1]:

详细见:Oracle 分区表性能优化


2. 原理

2.1 裁剪

- 查询条件
- 优化器判断
- 仅扫描相关分区
- 减少 I/O

2.2 优势

- I/O 减少
- 性能提升
- 透明

3. 静态裁剪

3.1 条件常量

SELECT * FROM sales 
WHERE sale_date = DATE '2025-07-21';
-- 仅扫描 p2025_07 分区

3.2 执行计划

PARTITION RANGE SINGLE
- 仅一个分区

3.3 多分区

SELECT * FROM sales 
WHERE sale_date BETWEEN DATE '2025-07-01' AND DATE '2025-07-31';
-- 扫描 p2025_07

4. 动态裁剪

4.1 绑定变量

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

4.2 子查询

SELECT * FROM sales 
WHERE sale_date IN (SELECT date_col FROM dates);
-- 动态裁剪

4.3 执行计划

PARTITION RANGE ITERATOR
PARTITION RANGE SINGLE
- 动态判断

5. 分区类型

5.1 RANGE

PARTITION BY RANGE (sale_date) (
  PARTITION p2025_01 VALUES LESS THAN (TO_DATE('2025-02-01', 'YYYY-MM-DD')),
  ...
);

5.2 LIST

PARTITION BY LIST (region) (
  PARTITION p_north VALUES ('BJ', 'TJ'),
  PARTITION p_south VALUES ('SH', 'GZ')
);

5.3 HASH

PARTITION BY HASH (id) PARTITIONS 8;
-- HASH 裁剪有限

5.4 组合

PARTITION BY RANGE (sale_date)
  SUBPARTITION BY LIST (region) (...);

详细见:Oracle 表分区策略详解


6. 查看裁剪

6.1 执行计划

EXPLAIN PLAN FOR SELECT * FROM sales WHERE sale_date = DATE '2025-07-21';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY));

6.2 关键字

- PARTITION RANGE SINGLE:单分区
- PARTITION RANGE ITERATOR:多分区
- PARTITION RANGE ALL:全部分区(未裁剪)
- PARTITION LIST SINGLE
- PARTITION HASH SINGLE

7. 优化

7.1 索引

- Local Index:分区裁剪 + 索引
- Global Index:限制裁剪

7.2 约束

-- 检查约束帮助裁剪
ALTER TABLE sales ADD CONSTRAINT ck_date 
  CHECK (sale_date >= DATE '2025-01-01');

7.3 统计

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

8. 应用场景

8.1 时间范围

- 日期分区
- 时间查询
- 裁剪

8.2 地域

- 地区分区
- 地区查询
- 裁剪

8.3 组合

- 时间 + 地区
- 组合分区
- 双重裁剪

9. 限制

9.1 函数

-- 不会裁剪
SELECT * FROM sales WHERE TO_CHAR(sale_date, 'YYYY') = '2025';
-- 改用
SELECT * FROM sales WHERE sale_date >= DATE '2025-01-01' AND sale_date < DATE '2026-01-01';

9.2 类型

- 隐式转换
- 避免函数

9.3 HASH

- HASH 分区
- 仅等值裁剪
- 范围无法裁剪

10. 监控

10.1 执行计划

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id'));

10.2 分区访问

SELECT * FROM v$sql_plan 
WHERE operation LIKE 'PARTITION%';

10.3 性能

SELECT sql_id, executions, disk_reads, buffer_gets
FROM v$sql
ORDER BY disk_reads DESC;

11. 常见问题

11.1 未裁剪

- 函数阻止
- 类型转换
- 检查

11.2 全分区扫描

- 条件不匹配
- 优化

11.3 性能

- 监控
- 优化
- 测试

12. 最佳实践

  1. 分区键查询:必用
  2. 避免函数:阻止裁剪
  3. Local Index:分区级
  4. 统计:分区级
  5. 执行计划:验证
  6. 测试:性能
  7. 组合分区:场景
  8. HASH:等值
  9. 文档:设计
  10. 监控:使用

13. 参考资料

[1] Oracle Database VLDB and Partitioning Guide 19c, “Partition Pruning” https://docs.oracle.com/en/database/oracle/oracle-database/19/vldbg/