Oracle AskTOM 分区表最佳实践
Oracle AskTOM 分区表最佳实践
来源:AskTOM (asktom.oracle.com) 适用版本:Oracle Database 8i+ / 19c / 23ai 文档版本:v1.0 / 2026-07-22
1. 概述
分区表是 Tom Kyte 在 AskTOM 多次讨论的主题[1]。
详细见:Oracle 分区表设计详解、Oracle 分区表性能优化。
2. Tom Kyte 核心观点
2.1 分区不是性能银弹
- 分区解决管理问题
- 性能取决于分区消除
- 错误分区 → 性能更差
- 按业务设计
2.2 分区主要目的
- 管理(可用性)
- 维护(删除、归档)
- 性能(分区消除、并行)
3. 分区类型
3.1 Range
CREATE TABLE orders (
id NUMBER,
order_date DATE
)
PARTITION BY RANGE (order_date) (
PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01','YYYY-MM-DD')),
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'))
);
3.2 List
CREATE TABLE customers (
id NUMBER,
region VARCHAR2(20)
)
PARTITION BY LIST (region) (
PARTITION p_north VALUES ('北京','上海'),
PARTITION p_south VALUES ('广州','深圳')
);
3.3 Hash
CREATE TABLE emp (
id NUMBER
)
PARTITION BY HASH (id) PARTITIONS 8;
3.4 Composite
-- Range + List / Hash
PARTITION BY RANGE (order_date)
SUBPARTITION BY LIST (region)
4. 何时分区
4.1 Tom 建议
- 表大于 2GB
- 按时间归档
- 维护窗口
- 并行处理
4.2 业务场景
- 日志表:按天/月
- 订单表:按月
- 历史表:按年
- 大数据表:Hash
4.3 不分区
- 小表
- 不可预测查询
- 简单 OLTP
5. 分区消除
5.1 原理
- 查询条件包含分区键
- CBO 跳过无关分区
- 性能提升
5.2 示例
-- 分区消除
SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31';
-- 只扫描 p2024
5.3 失效
-- 函数导致失效
SELECT * FROM orders
WHERE TO_CHAR(order_date,'YYYY') = '2024';
-- 扫描所有分区
6. 分区策略
6.1 按时间
- Range
- 月/季度/年
- 便于归档
6.2 按业务
- List
- 地区/类型
- 便于管理
6.3 按数据
- Hash
- 均匀分布
- 大数据
7. 维护操作
7.1 添加
ALTER TABLE orders ADD PARTITION p2026
VALUES LESS THAN (TO_DATE('2027-01-01','YYYY-MM-DD'));
7.2 删除
ALTER TABLE orders DROP PARTITION p2023;
-- 快速删除大量数据
7.3 交换
ALTER TABLE orders EXCHANGE PARTITION p2023
WITH TABLE orders_archive;
-- 数据迁移
7.4 合并
ALTER TABLE orders MERGE PARTITIONS p2023, p2024
INTO PARTITION p2023_2024;
7.5 拆分
ALTER TABLE orders SPLIT PARTITION p2023_2024
AT (TO_DATE('2024-01-01','YYYY-MM-DD'))
INTO (PARTITION p2023, PARTITION p2024);
8. 索引
8.1 Local Index
- 每分区独立
- 易维护
- 推荐
CREATE INDEX idx_orders_local ON orders(order_date) LOCAL;
8.2 Global Index
- 跨分区
- 维护成本
- 慎用
CREATE INDEX idx_orders_global ON orders(customer_id) GLOBAL;
8.3 Tom 建议
- 优先 Local
- Global 慎用
- 维护成本高
9. 11g+ 新特性
9.1 Interval
CREATE TABLE orders (...)
PARTITION BY RANGE (order_date)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION p0 VALUES LESS THAN (TO_DATE('2024-01-01','YYYY-MM-DD'))
);
-- 自动创建分区
9.2 Reference
-- 子表按父表分区
PARTITION BY REFERENCE (fk_orders);
9.3 Virtual
- 虚拟列分区
- 灵活
10. 监控
10.1 分区信息
SELECT table_name, partition_name, num_rows, bytes
FROM user_tab_partitions;
10.2 分区统计
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'ORDERS');
10.3 查询分区
SELECT * FROM orders PARTITION (p2024);
11. 常见问题
11.1 性能下降
- 分区消除失效
- 检查查询
- 优化
11.2 ORA-14400
- 插入无匹配分区
- 添加分区
- 或 Interval
11.3 Global Index 失效
- 分区操作
- 重建
- Local 优先
12. 最佳实践
- 按业务:设计
- 分区消除:保证
- Local Index:优先
- Interval:自动
- 统计信息:收集
- 监控:分区大小
- 归档:定期
- 测试:性能
- 文档:策略
- 评估:定期
13. 参考资料
[1] AskTOM, “Partitioning Best Practices”, https://asktom.oracle.com [2] Oracle Database VLDB and Partitioning Guide 19c