Part02-生产环境规划与建议
2.1 分区裁剪配置
分区裁剪的配置参数:
- OPTIMIZER_FEATURES_ENABLE:控制优化器特性的启用
- PARTITION_PRUNING:控制分区裁剪的启用
- PARALLEL_DEGREE_POLICY:控制并行执行策略
- DB_FILE_MULTIBLOCK_READ_COUNT:控制多块读取的大小
风哥提示:在生产环境中,应根据系统的硬件配置和 workload 特点选择合适的分区裁剪配置。
2.2 分区裁剪策略
分区裁剪的策略:
- 使用分区键作为查询条件:在WHERE子句中使用分区键作为查询条件
- 避免在分区键上使用函数:避免在分区键上使用函数,以免影响分区裁剪
- 使用绑定变量:合理使用绑定变量,避免因绑定变量导致分区裁剪失效
- 收集统计信息:定期收集分区表的统计信息,确保优化器能够正确进行分区裁剪
- 监控分区裁剪:定期监控分区裁剪的效果,及时发现和解决问题
- 选择合适的分区策略:根据数据特点选择合适的分区策略,提高分区裁剪的效果
更多学习教程公众号风哥教程itpux_com
2.3 分区裁剪注意事项
分区裁剪的注意事项:
- 分区键选择:选择合适的分区键,确保查询能够有效地进行分区裁剪
- 查询条件:确保查询条件中包含分区键,以便进行分区裁剪
- 函数使用:避免在分区键上使用函数,以免影响分区裁剪
- 绑定变量:注意绑定变量对分区裁剪的影响
- 统计信息:确保分区表的统计信息准确,以便优化器能够正确进行分区裁剪
- 执行计划:监控执行计划,确保分区裁剪正常工作
- 分区维护:定期维护分区表,确保分区结构合理
from oracle:www.itpux.com
Part03-生产环境项目实施方案
在生产环境中实施分区裁剪的实施方案:
- 评估数据特点:评估数据的特点,确定是否适合使用分区表。
- 选择分区策略:根据数据特点选择合适的分区策略,如范围分区、列表分区、哈希分区等。
- 设计分区键:选择合适的分区键,确保查询能够有效地进行分区裁剪。
- 创建分区表:创建分区表,设置合理的分区结构。
- 测试分区裁剪:测试分区裁剪的效果,确保查询能够正确进行分区裁剪。
- 部署实施:在生产环境中部署分区表。
- 监控维护:定期监控分区裁剪的效果,及时发现和解决问题。
- 优化调整:根据监控结果调整分区结构,优化分区裁剪效果。
Part04-生产案例与实战讲解
4.1 范围分区裁剪
示例:范围分区裁剪
CREATE TABLE sales_range (
sale_id NUMBER PRIMARY KEY,
sale_date DATE,
product_id NUMBER,
quantity NUMBER,
amount NUMBER
)
PARTITION BY RANGE (sale_date) (
PARTITION p2023 QVALUES 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’)),
PARTITION p2026 VALUES LESS THAN (TO_DATE(‘2027-01-01’, ‘YYYY-MM-DD’))
);– 插入测试数据
INSERT INTO sales_range VALUES (1, TO_DATE(‘2023-06-01’, ‘YYYY-MM-DD’), 1001, 10, 1000);INSERT INTO sales_range VALUES (2, TO_DATE(‘2024-06-01’, ‘YYYY-MM-DD’), 1002, 20, 2000);INSERT INTO sales_range VALUES (3, TO_DATE(‘2025-06-01’, ‘YYYY-MM-DD’), 1003, 30, 3000);INSERT INTO sales_range VALUES (4, TO_DATE(‘2026-06-01’, ‘YYYY-MM-DD’), 1004, 40, 4000);– 测试分区裁剪:只访问p2024分区
SELECT * FROM sales_range WHERE sale_date BETWEEN TO_DATE(‘2024-01-01’, ‘YYYY-MM-DD’) AND
TO_DATE(‘2024-12-31’, ‘YYYY-MM-DD’);– 测试分区裁剪:访问p2024和p2025分区
SELECT * FROM sales_range WHERE sale_date BETWEEN TO_DATE(‘2024-06-01’, ‘YYYY-MM-DD’) AND
TO_DATE(‘2025-06-30’, ‘YYYY-MM-DD’);– 测试分区裁剪:访问所有分区(没有裁剪)
SELECT * FROM sales_range;
Execution Plan
———————————————————-
Plan hash value: 3898747075
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 1 | 41 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE SINGLE | | 1 | 41 | 2 (0)| 00:00:01 | 2 | 2 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_RANGE | 1 | 41 | 2 (0)| 00:00:01 | 2 | 2 |
|* 3 | INDEX RANGE SCAN | SYS_C001234 | 1 | | 1 (0)| 00:00:01 | 2 | 2 |
—————————————————————————————————-
— 测试分区裁剪:访问p2024和p2025分区
Execution Plan
———————————————————-
Plan hash value: 3898747075
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 2 | 82 | 4 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ITERATOR | | 2 | 82 | 4 (0)| 00:00:01 | 2 | 3 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_RANGE | 2 | 82 | 4 (0)| 00:00:01 | 2 | 3 |
|* 3 | INDEX RANGE SCAN | SYS_C001234 | 2 | | 2 (0)| 00:00:01 | 2 | 3 |
—————————————————————————————————-
— 测试分区裁剪:访问所有分区(没有裁剪)
Execution Plan
———————————————————-
Plan hash value: 3898747075
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 4 | 164 | 8 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL | | 4 | 164 | 8 (0)| 00:00:01 | 1 | 4 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_RANGE | 4 | 164 | 8 (0)| 00:00:01 | 1 | 4 |
|* 3 | INDEX RANGE SCAN | SYS_C001234 | 4 | | 4 (0)| 00:00:01 | 1 | 4 |
—————————————————————————————————-
更多视频教程www.fgedu.net.cn
4.2 列表分区裁剪
示例:列表分区裁剪
CREATE TABLE sales_list (
sale_id NUMBER PRIMARY KEY,
sale_date DATE,
region VARCHAR2(50),
product_id NUMBER,
quantity NUMBER,
amount NUMBER
)
PARTITION BY LIST (region) (
PARTITION p_north VALUES (‘North’, ‘Northeast’),
PARTITION p_south VALUES (‘South’, ‘Southeast’),
PARTITION p_west VALUES (‘West’, ‘Southwest’),
PARTITION p_east VALUES (‘East’, ‘Southeast’)
);– 插入测试数据
INSERT INTO sales_list VALUES (1, TO_DATE(‘2026-01-01’, ‘YYYY-MM-DD’), ‘North’, 1001, 10, 1000);INSERT INTO sales_list VALUES (2, TO_DATE(‘2026-01-02’, ‘YYYY-MM-DD’), ‘South’, 1002, 20, 2000);INSERT INTO sales_list VALUES (3, TO_DATE(‘2026-01-03’, ‘YYYY-MM-DD’), ‘West’, 1003, 30, 3000);INSERT INTO sales_list VALUES (4, TO_DATE(‘2026-01-04’, ‘YYYY-MM-DD’), ‘East’, 1004, 40, 4000);– 测试分区裁剪:只访问p_north分区
SELECT * FROM sales_list WHERE region = ‘North’;– 测试分区裁剪:访问p_north和p_south分区
SELECT * FROM sales_list WHERE region IN (‘North’, ‘South’);– 测试分区裁剪:访问所有分区(没有裁剪)
SELECT * FROM sales_list;
Execution Plan
———————————————————-
Plan hash value: 1234567890
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 1 | 51 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION LIST SINGLE | | 1 | 51 | 2 (0)| 00:00:01 | 1 | 1 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_LIST | 1 | 51 | 2 (0)| 00:00:01 | 1 | 1 |
|* 3 | INDEX RANGE SCAN | SYS_C001235 | 1 | | 1 (0)| 00:00:01 | 1 | 1 |
—————————————————————————————————-
— 测试分区裁剪:访问p_north和p_south分区
Execution Plan
———————————————————-
Plan hash value: 1234567890
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 2 | 102 | 4 (0)| 00:00:01 | | |
| 1 | PARTITION LIST ITERATOR | | 2 | 102 | 4 (0)| 00:00:01 | 1 | 2 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_LIST | 2 | 102 | 4 (0)| 00:00:01 | 1 | 2 |
|* 3 | INDEX RANGE SCAN | SYS_C001235 | 2 | | 2 (0)| 00:00:01 | 1 | 2 |
—————————————————————————————————-
— 测试分区裁剪:访问所有分区(没有裁剪)
Execution Plan
———————————————————-
Plan hash value: 1234567890
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 4 | 204 | 8 (0)| 00:00:01 | | |
| 1 | PARTITION LIST ALL | | 4 | 204 | 8 (0)| 00:00:01 | 1 | 4 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_LIST | 4 | 204 | 8 (0)| 00:00:01 | 1 | 4 |
|* 3 | INDEX RANGE SCAN | SYS_C001235 | 4 | | 4 (0)| 00:00:01 | 1 | 4 |
—————————————————————————————————-
学习交流加群风哥微信: itpux-com
4.3 哈希分区裁剪
示例:哈希分区裁剪
CREATE TABLE sales_hash (
sale_id NUMBER PRIMARY KEY,
sale_date DATE,
product_id NUMBER,
quantity NUMBER,
amount NUMBER
)
PARTITION BY HASH (product_id) (
PARTITION p1,
PARTITION p2,
PARTITION p3,
PARTITION p4
);– 插入测试数据
INSERT INTO sales_hash VALUES (1, TO_DATE(‘2026-01-01’, ‘YYYY-MM-DD’), 1001, 10, 1000);INSERT INTO sales_hash VALUES (2, TO_DATE(‘2026-01-02’, ‘YYYY-MM-DD’), 1002, 20, 2000);INSERT INTO sales_hash VALUES (3, TO_DATE(‘2026-01-03’, ‘YYYY-MM-DD’), 1003, 30, 3000);INSERT INTO sales_hash VALUES (4, TO_DATE(‘2026-01-04’, ‘YYYY-MM-DD’), 1004, 40, 4000);– 测试分区裁剪:只访问一个哈希分区
SELECT * FROM sales_hash WHERE product_id = 1001;– 测试分区裁剪:访问多个哈希分区
SELECT * FROM sales_hash WHERE product_id IN (1001, 1002);– 测试分区裁剪:访问所有分区(没有裁剪)
SELECT * FROM sales_hash;
Execution Plan
———————————————————-
Plan hash value: 9876543210
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 1 | 41 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION HASH SINGLE | | 1 | 41 | 2 (0)| 00:00:01 | 1 | 1 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_HASH | 1 | 41 | 2 (0)| 00:00:01 | 1 | 1 |
|* 3 | INDEX RANGE SCAN | SYS_C001236 | 1 | | 1 (0)| 00:00:01 | 1 | 1 |
—————————————————————————————————-
— 测试分区裁剪:访问多个哈希分区
Execution Plan
———————————————————-
Plan hash value: 9876543210
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 2 | 82 | 4 (0)| 00:00:01 | | |
| 1 | PARTITION HASH ITERATOR | | 2 | 82 | 4 (0)| 00:00:01 | 1 | 4 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_HASH | 2 | 82 | 4 (0)| 00:00:01 | 1 | 4 |
|* 3 | INDEX RANGE SCAN | SYS_C001236 | 2 | | 2 (0)| 00:00:01 | 1 | 4 |
—————————————————————————————————-
— 测试分区裁剪:访问所有分区(没有裁剪)
Execution Plan
———————————————————-
Plan hash value: 9876543210
—————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
—————————————————————————————————-
| 0 | SELECT STATEMENT | | 4 | 164 | 8 (0)| 00:00:01 | | |
| 1 | PARTITION HASH ALL | | 4 | 164 | 8 (0)| 00:00:01 | 1 | 4 |
| 2 | TABLE ACCESS BY LOCAL INDEX ROWID| SALES_HASH | 4 | 164 | 8 (0)| 00:00:01 | 1 | 4 |
|* 3 | INDEX RANGE SCAN | SYS_C001236 | 4 | | 4 (0)| 00:00:01 | 1 | 4 |
—————————————————————————————————-
学习交流加群风哥QQ113257174
4.4 复合分区裁剪
示例:复合分区裁剪
CREATE TABLE sales_composite (
sale_id NUMBER PRIMARY KEY,
sale_date DATE,
region VARCHAR2(50),
product_id NUMBER,
quantity NUMBER,
amount NUMBER
)
PARTITION BY RANGE (sale_date)
SUBPARTITION BY LIST (region) (
PARTITION p2024 VALUES LESS THAN (TO_DATE(‘2025-01-01’, ‘YYYY-MM-DD’)) (
SUBPARTITION p2024_north VALUES (‘North’, ‘Northeast’),
SUBPARTITION p2024_south VALUES (‘South’, ‘Southeast’),
SUBPARTITION p2024_west VALUES (‘West’, ‘Southwest’),
SUBPARTITION p2024_east VALUES (‘East’, ‘Southeast’)
),
PARTITION p2025 VALUES LESS THAN (TO_DATE(‘2026-01-01’, ‘YYYY-MM-DD’)) (
SUBPARTITION p2025_north VALUES (‘North’, ‘Northeast’),
SUBPARTITION p2025_south VALUES (‘South’, ‘Southeast’),
SUBPARTITION p2025_west VALUES (‘West’, ‘Southwest’),
SUBPARTITION p2025_east VALUES (‘East’, ‘Southeast’)
)
);– 插入测试数据
INSERT INTO sales_composite VALUES (1, TO_DATE(‘2024-06-01’, ‘YYYY-MM-DD’), ‘North’, 1001, 10, 1000);INSERT INTO sales_composite VALUES (2, TO_DATE(‘2024-06-02’, ‘YYYY-MM-DD’), ‘South’, 1002, 20, 2000);INSERT INTO sales_composite VALUES (3, TO_DATE(‘2025-06-01’, ‘YYYY-MM-DD’), ‘North’, 1003, 30, 3000);INSERT INTO sales_composite VALUES (4, TO_DATE(‘2025-06-02’, ‘YYYY-MM-DD’), ‘South’, 1004, 40, 4000);– 测试分区裁剪:只访问p2024_north子分区
SELECT * FROM sales_composite WHERE sale_date BETWEEN TO_DATE(‘2024-01-01’, ‘YYYY-MM-DD’) AND TO_DATE(‘2024-12-31’, ‘YYYY-MM-DD’) AND region = ‘North’;– 测试分区裁剪:访问p2024_north和p2024_south子分区
SELECT * FROM sales_composite WHERE sale_date BETWEEN TO_DATE(‘2024-01-01’, ‘YYYY-MM-DD’) AND TO_DATE(‘2024-12-31’, ‘YYYY-MM-DD’) AND region IN (‘North’, ‘South’);– 测试分区裁剪:访问p2024和p2025的north子分区
SELECT * FROM sales_composite WHERE region = ‘North’;
Execution Plan
———————————————————-
Plan hash value: 5678901234
———————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | IN-OUT |
———————————————————————————————————-
| 0 | SELECT STATEMENT | | 1 | 51 | 2 (0)| 00:00:01 | | | |
| 1 | PARTITION RANGE SINGLE | | 1 | 51 | 2 (0)| 00:00:01 | 1 | 1 | |
| 2 | PARTITION LIST SINGLE | | 1 | 51 | 2 (0)| 00:00:01 | 1 | 1 | |
| 3 | TABLE ACCESS BY LOCAL INDEX ROWID | SALES_COMPOSITE | 1 | 51 | 2 (0)| 00:00:01 | 1 | 1 | |
|* 4 | INDEX RANGE SCAN | SYS_C001237 | 1 | | 1 (0)| 00:00:01 | 1 | 1 | |
———————————————————————————————————-
— 测试分区裁剪:访问p2024_north和p2024_south子分区
Execution Plan
———————————————————-
Plan hash value: 5678901234
———————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | IN-OUT |
———————————————————————————————————-
| 0 | SELECT STATEMENT | | 2 | 102 | 4 (0)| 00:00:01 | | | |
| 1 | PARTITION RANGE SINGLE | | 2 | 102 | 4 (0)| 00:00:01 | 1 | 1 | |
| 2 | PARTITION LIST ITERATOR | | 2 | 102 | 4 (0)| 00:00:01 | 1 | 2 | |
| 3 | TABLE ACCESS BY LOCAL INDEX ROWID | SALES_COMPOSITE | 2 | 102 | 4 (0)| 00:00:01 | 1 | 2 | |
|* 4 | INDEX RANGE SCAN | SYS_C001237 | 2 | | 2 (0)| 00:00:01 | 1 | 2 | |
———————————————————————————————————-
— 测试分区裁剪:访问p2024和p2025的north子分区
Execution Plan
———————————————————-
Plan hash value: 5678901234
———————————————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | IN-OUT |
———————————————————————————————————-
| 0 | SELECT STATEMENT | | 2 | 102 | 4 (0)| 00:00:01 | | | |
| 1 | PARTITION RANGE ITERATOR | | 2 | 102 | 4 (0)| 00:00:01 | 1 | 2 | |
| 2 | PARTITION LIST SINGLE | | 2 | 102 | 4 (0)| 00:00:01 | 1 | 1 | |
| 3 | TABLE ACCESS BY LOCAL INDEX ROWID | SALES_COMPOSITE | 2 | 102 | 4 (0)| 00:00:01 | 1 | 1 | |
|* 4 | INDEX RANGE SCAN | SYS_C001237 | 2 | | 2 (0)| 00:00:01 | 1 | 1 | |
———————————————————————————————————-
学习交流加群风哥QQ113257174
Part05-风哥经验总结与分享
风哥提示:在使用分区裁剪时,应注意以下几点:
- 选择合适的分区键:选择经常用于查询条件的列作为分区键,以提高分区裁剪的效果。
- 在查询条件中使用分区键:确保查询条件中包含分区键,以便进行分区裁剪。
- 避免在分区键上使用函数:避免在分区键上使用函数,以免影响分区裁剪。
- 合理使用绑定变量:注意绑定变量对分区裁剪的影响,避免因绑定变量导致分区裁剪失效。
- 收集统计信息:定期收集分区表的统计信息,确保优化器能够正确进行分区裁剪。
- 监控分区裁剪:定期监控分区裁剪的效果,及时发现和解决问题。
- 选择合适的分区策略:根据数据特点选择合适的分区策略,提高分区裁剪的效果。
- 合理设计分区结构:合理设计分区结构,确保分区裁剪能够有效地减少数据扫描范围。
- 测试分区裁剪:在使用分区表前,测试分区裁剪的效果,确保查询能够正确进行分区裁剪。
- 结合其他优化手段:分区裁剪应与其他优化手段结合使用,如索引优化、SQL重写等。
更多学习教程公众号风哥教程itpux_com
from:风哥.QQ113257174.WX:itpux-com,web: http://www.fgedu.net.cn
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
