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. 最佳实践
- 分区键查询:必用
- 避免函数:阻止裁剪
- Local Index:分区级
- 统计:分区级
- 执行计划:验证
- 测试:性能
- 组合分区:场景
- HASH:等值
- 文档:设计
- 监控:使用
13. 参考资料
[1] Oracle Database VLDB and Partitioning Guide 19c, “Partition Pruning” https://docs.oracle.com/en/database/oracle/oracle-database/19/vldbg/