

文章目录
正文
当你已经掌握了Oracle的基础语法,现在是时候踏入Oracle的高级殿堂了!这里有着令人兴奋的高级特性,就像是从使用计算器升级到掌握超级计算机一样。Oracle的高级功能不仅能让你的数据库性能飞起来,还能让你在同事面前秀出真正的技术实力!
🚀 性能优化篇:让Oracle跑得飞快
1. 执行计划分析 - 数据库的"透视眼"
执行计划就像是Oracle的"思维导图",告诉你数据库是如何思考和执行你的SQL的。
-- 最强大的执行计划分析工具
EXPLAIN PLAN FOR
SELECT /*+ GATHER_PLAN_STATISTICS */
e.employee_id,
e.first_name || ' ' || e.last_name AS full_name,
d.department_name,
j.job_title,
e.salary,
RANK() OVER (PARTITION BY d.department_id ORDER BY e.salary DESC) as salary_rank
FROM employees e
JOIN departments d ON e.department_id = d.department_id
JOIN jobs j ON e.job_id = j.job_id
WHERE e.hire_date >= ADD_MONTHS(SYSDATE, -24)
AND e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);
-- 查看详细执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, NULL, 'ALL +IOSTATS +MEMSTATS'));
-- 🔥 高级技巧:实时监控SQL执行
SELECT sql_id, child_number, operation, options, object_name,
cost, cardinality, bytes, cpu_cost, io_cost
FROM v$sql_plan
WHERE sql_id = '&sql_id'
ORDER BY id;
-- 神器:AWR报告生成(DBA必备)
BEGIN
DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;
END;
/
-- 24小时后生成性能报告
SELECT output FROM TABLE(
DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_TEXT(
l_dbid => (SELECT dbid FROM v$database),
l_inst_num => 1,
l_bid => &begin_snap_id,
l_eid => &end_snap_id
)
);
2. 索引优化策略 - 数据库的"导航系统"
-- 🎯 智能索引分析和优化建议
WITH index_usage_stats AS (
SELECT
i.index_name,
i.table_name,
i.uniqueness,
i.index_type,
ius.total_access_count,
ius.total_exec_count,
ius.bucket_0_access_count,
ROUND(ius.total_access_count / NULLIF(ius.total_exec_count, 0), 2) as avg_access_per_exec
FROM user_indexes i
LEFT JOIN v$index_usage_stats ius ON i.index_name = ius.name
WHERE i.table_name IN ('EMPLOYEES', 'ORDERS', 'CUSTOMERS')
)
SELECT
index_name,
table_name,
uniqueness,
total_access_count,
avg_access_per_exec,
CASE
WHEN total_access_count = 0 THEN '❌ 从未使用 - 考虑删除'
WHEN avg_access_per_exec < 0.1 THEN '⚠️ 使用率低 - 需要优化'
WHEN avg_access_per_exec > 10 THEN '🚀 高效索引 - 保持'
ELSE '✅ 正常使用'
END as recommendation
FROM index_usage_stats
ORDER BY total_access_count DESC NULLS LAST;
-- 🔍 自动索引建议生成器
DECLARE
l_task_name VARCHAR2(30) := 'AUTO_INDEX_ADVISOR_' || TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS');
l_task_id NUMBER;
BEGIN
-- 创建SQL调优任务
l_task_id := DBMS_SQLTUNE.CREATE_TUNING_TASK(
sql_text => 'SELECT * FROM employees e JOIN departments d ON e.department_id = d.department_id WHERE e.salary > 5000',
task_name => l_task_name,
description => '自动索引优化建议'
);
-- 执行调优分析
DBMS_SQLTUNE.EXECUTE_TUNING_TASK(l_task_name);
-- 查看建议
SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK(l_task_name) FROM dual;
END;
/
-- 💡 函数索引的高级应用
CREATE INDEX idx_emp_upper_name ON employees(UPPER(first_name || ' ' || last_name));
CREATE INDEX idx_order_date_year ON orders(EXTRACT(YEAR FROM order_date));
CREATE INDEX idx_salary_range ON employees(
CASE
WHEN salary < 3000 THEN 'LOW'
WHEN salary < 8000 THEN 'MEDIUM'
ELSE 'HIGH'
END
);
-- 🎪 压缩索引节省空间
CREATE INDEX idx_emp_dept_job_compressed ON employees(department_id, job_id, salary)
COMPRESS 2; -- 压缩前两列
-- 查看压缩效果
SELECT index_name, compression, leaf_blocks, distinct_keys,
ROUND(leaf_blocks * 8192 / 1024 / 1024, 2) as size_mb
FROM user_indexes
WHERE table_name = 'EMPLOYEES';
3. 分区表的威力 - 数据库的"分治策略"
-- 🏗️ 超级分区表设计:范围+哈希混合分区
CREATE TABLE sales_super_partitioned (
sale_id NUMBER(12),
sale_date DATE NOT NULL,
customer_id NUMBER(10) NOT NULL,
product_id NUMBER(10) NOT NULL,
region_id NUMBER(4) NOT NULL,
amount NUMBER(12,2) NOT NULL,
sales_rep_id NUMBER(6),
created_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
PARTITION BY RANGE (sale_date)
SUBPARTITION BY HASH (customer_id) SUBPARTITIONS 8 (
PARTITION sales_2023 VALUES LESS THAN (DATE '2024-01-01'),
PARTITION sales_2024_q1 VALUES LESS THAN (DATE '2024-04-01'),
PARTITION sales_2024_q2 VALUES LESS THAN (DATE '2024-07-01'),
PARTITION sales_2024_q3 VALUES LESS THAN (DATE '2024-10-01'),
PARTITION sales_2024_q4 VALUES LESS THAN (DATE '2025-01-01'),
PARTITION sales_future VALUES LESS THAN (MAXVALUE)
);
-- 🎯 智能分区维护自动化
CREATE OR REPLACE PROCEDURE maintain_partitions
IS
v_partition_name VARCHAR2(30);
v_next_quarter_start DATE;
v_partition_exists NUMBER;
BEGIN
-- 计算下个季度开始日期
v_next_quarter_start := ADD_MONTHS(TRUNC(SYSDATE, 'Q'), 3);
v_partition_name := 'SALES_' || TO_CHAR(v_next_quarter_start, 'YYYY_Q"Q"');
-- 检查分区是否存在
SELECT COUNT(*) INTO v_partition_exists
FROM user_tab_partitions
WHERE table_name = 'SALES_SUPER_PARTITIONED'
AND partition_name = v_partition_name;
-- 如果不存在,自动创建
IF v_partition_exists = 0 THEN
EXECUTE IMMEDIATE
'ALTER TABLE sales_super_partitioned
SPLIT PARTITION sales_future
AT (DATE ''' || TO_CHAR(v_next_quarter_start, 'YYYY-MM-DD') || ''')
INTO (PARTITION ' || v_partition_name || ', PARTITION sales_future)';
DBMS_OUTPUT.PUT_LINE('✅ 自动创建分区: ' || v_partition_name);
END IF;
-- 清理超过3年的历史分区
FOR old_partition IN (
SELECT partition_name, high_value
FROM user_tab_partitions
WHERE table_name = 'SALES_SUPER_PARTITIONED'
AND partition_name LIKE 'SALES_2%'
AND partition_name < 'SALES_' || TO_CHAR(ADD_MONTHS(SYSDATE, -36), 'YYYY')
) LOOP
EXECUTE IMMEDIATE 'ALTER TABLE sales_super_partitioned DROP PARTITION ' || old_partition.partition_name;
DBMS_OUTPUT.PUT_LINE('🗑️ 清理历史分区: ' || old_partition.partition_name);
END LOOP;
END;
/
-- 📊 分区性能监控仪表板
WITH partition_stats AS (
SELECT
table_name,
partition_name,
num_rows,
blocks,
empty_blocks,
avg_space,
chain_cnt,
avg_row_len,
sample_size,
last_analyzed,
ROUND(blocks * 8192 / 1024 / 1024, 2) as size_mb
FROM user_tab_partitions
WHERE table_name = 'SALES_SUPER_PARTITIONED'
)
SELECT
partition_name,
TO_CHAR(num_rows, '999,999,999') as row_count,
size_mb || ' MB' as partition_size,

最低0.47元/天 解锁文章
1797

被折叠的 条评论
为什么被折叠?



