☰
Oracle 12c SQL监控与性能优化实战指南
2026/11/3 6:57:27 网站建设 项目流程

1. 项目概述

作为一名DBA,我们经常需要排查数据库性能问题或者审计SQL执行情况。Oracle 12c作为企业级数据库,提供了多种方式来查看历史执行过的SQL以及当前正在执行的SQL语句。掌握这些方法对于数据库性能调优、故障排查和安全审计都至关重要。

在实际工作中,我经常遇到需要追踪某个性能问题的SQL源头,或者需要监控当前数据库负载情况。通过系统视图和动态性能视图,我们可以获取到丰富的信息,包括SQL文本、执行计划、资源消耗等关键数据。

2. 核心视图与工具解析

2.1 V$SQL与V$SQLAREA视图

V$SQL和V$SQLAREA是Oracle中最常用的两个动态性能视图,用于查看当前共享池中的SQL语句。

V$SQL视图包含共享SQL区域中每个子游标的信息,而V$SQLAREA视图则包含共享SQL区域的统计信息,按SQL文本分组。这两个视图的主要区别在于粒度不同:

  • V$SQL:更细粒度,每个子游标一条记录
  • V$SQLAREA:按SQL文本聚合,相同SQL文本只显示一条记录

查询示例:

SELECT sql_id, sql_text, executions, buffer_gets, disk_reads FROM v$sql WHERE sql_text LIKE '%SELECT%FROM employees%';

2.2 V$SESSION与V$SQLSTATS视图

V$SESSION视图显示当前会话信息,结合V$SQL可以查看当前正在执行的SQL:

SELECT s.sid, s.serial#, s.username, s.status, q.sql_id, q.sql_text FROM v$session s JOIN v$sql q ON s.sql_id = q.sql_id WHERE s.status = 'ACTIVE';

V$SQLSTATS视图提供了SQL语句执行的统计信息,对于性能分析特别有用:

SELECT sql_id, executions, elapsed_time/1000000 as elapsed_sec, cpu_time/1000000 as cpu_sec, buffer_gets, disk_reads FROM v$sqlstats ORDER BY elapsed_time DESC;

3. 历史SQL查询方法

3.1 AWR报告分析

AWR(Automatic Workload Repository)是Oracle提供的自动负载信息库,默认每小时采集一次快照,保存7天。

生成AWR报告:

SELECT output FROM TABLE(dbms_workload_repository.awr_report_text( l_dbid => (SELECT dbid FROM v$database), l_inst_num => (SELECT instance_number FROM v$instance), l_bid => &begin_snap_id, l_eid => &end_snap_id));

报告中的"SQL Statistics"部分包含了这段时间内消耗资源最多的SQL语句。

3.2 ASH(Active Session History)分析

ASH每秒采样一次活动会话信息,保存在内存中,默认保留1小时。

查询最近15分钟的高负载SQL:

SELECT sql_id, COUNT(*) as active_sessions FROM v$active_session_history WHERE sample_time > SYSDATE - 15/1440 GROUP BY sql_id ORDER BY active_sessions DESC;

3.3 审计日志查询

如果启用了标准审计,可以通过DBA_AUDIT_TRAIL视图查询:

SELECT username, action_name, sql_text, timestamp FROM dba_audit_trail WHERE sql_text IS NOT NULL ORDER BY timestamp DESC;

4. 实时监控与性能分析

4.1 实时SQL监控

Oracle 12c提供了实时SQL监控功能,对于长时间运行的SQL特别有用:

SELECT dbms_sqltune.report_sql_monitor( sql_id => '&sql_id', type => 'TEXT', report_level => 'ALL') as report FROM dual;

4.2 SQL跟踪与分析

对于特定会话或SQL,可以启用SQL跟踪:

-- 会话级别跟踪 EXEC DBMS_MONITOR.session_trace_enable(session_id => 123, serial_num => 456); -- 实例级别跟踪 ALTER SYSTEM SET sql_trace = TRUE; -- 生成TKPROF报告 tkprof ora_12345.trc output.txt explain=scott/tiger

5. 实用查询脚本集锦

5.1 查找高资源消耗SQL

SELECT sql_id, executions, ROUND(elapsed_time/1000000,2) as elapsed_sec, ROUND(cpu_time/1000000,2) as cpu_sec, buffer_gets, disk_reads, sql_text FROM ( SELECT sql_id, executions, elapsed_time, cpu_time, buffer_gets, disk_reads, sql_text, RANK() OVER (ORDER BY elapsed_time DESC) as elapsed_rank FROM v$sqlstats WHERE executions > 0 ) WHERE elapsed_rank <= 10;

5.2 查找长时间运行会话

SELECT s.sid, s.serial#, s.username, s.status, s.machine, s.program, s.module, q.sql_id, q.sql_text, ROUND(s.last_call_et/60,2) as minutes_running FROM v$session s LEFT JOIN v$sql q ON s.sql_id = q.sql_id WHERE s.status = 'ACTIVE' AND s.last_call_et > 300 -- 运行超过5分钟 ORDER BY s.last_call_et DESC;

5.3 查找锁等待SQL

SELECT l.session_id, s.serial#, s.username, o.object_name, o.object_type, l.oracle_username, l.os_user_name, q.sql_text FROM v$locked_object l JOIN dba_objects o ON l.object_id = o.object_id JOIN v$session s ON l.session_id = s.sid LEFT JOIN v$sql q ON s.sql_id = q.sql_id;

6. 性能优化建议

6.1 SQL执行计划分析

获取SQL执行计划:

EXPLAIN PLAN FOR SELECT * FROM employees WHERE department_id = 10; SELECT * FROM TABLE(dbms_xplan.display);

6.2 绑定变量窥视问题

绑定变量窥视可能导致执行计划不优,可以通过以下SQL检查:

SELECT sql_id, child_number, executions, is_bind_sensitive, is_bind_aware, is_shareable FROM v$sql WHERE sql_id = '&sql_id';

6.3 SQL调优建议

使用SQL Tuning Advisor获取调优建议:

DECLARE l_task_name VARCHAR2(30); l_sql_id VARCHAR2(13) := '&sql_id'; BEGIN l_task_name := dbms_sqltune.create_tuning_task( sql_id => l_sql_id, scope => 'COMPREHENSIVE', time_limit => 60, description => 'Tuning task for SQL_ID ' || l_sql_id); dbms_sqltune.execute_tuning_task(l_task_name); END; / SELECT dbms_sqltune.report_tuning_task('&task_name') FROM dual;

7. 安全与权限考虑

7.1 必要权限

要查询这些视图,用户通常需要以下权限:

  • SELECT_CATALOG_ROLE
  • 或者针对特定视图的SELECT权限
GRANT SELECT ON v_$sql TO monitoring_user; GRANT SELECT ON v_$session TO monitoring_user;

7.2 敏感信息处理

查询结果中可能包含敏感数据,建议:

  1. 在生产环境谨慎分享完整SQL文本
  2. 对输出进行脱敏处理
  3. 遵守公司数据安全政策

8. 自动化监控方案

8.1 创建监控脚本

可以创建定期运行的Shell脚本,自动捕获高负载SQL:

#!/bin/bash ORACLE_HOME=/u01/app/oracle/product/12.2.0/dbhome_1 export ORACLE_SID=orcl export PATH=$ORACLE_HOME/bin:$PATH sqlplus -s "/ as sysdba" <<EOF SET PAGESIZE 1000 SET LINESIZE 200 SET HEADING ON SET FEEDBACK OFF SPOOL /tmp/high_load_sql_$(date +%Y%m%d_%H%M).log SELECT sql_id, executions, ROUND(elapsed_time/1000000,2) as elapsed_sec, ROUND(elapsed_time/1000000/NULLIF(executions,0),4) as sec_per_exec, buffer_gets, disk_reads, SUBSTR(sql_text,1,100) as sql_text FROM ( SELECT sql_id, executions, elapsed_time, buffer_gets, disk_reads, sql_text, RANK() OVER (ORDER BY elapsed_time DESC) as elapsed_rank FROM v\$sqlstats WHERE executions > 0 AND last_active_time > SYSDATE - 1/24 -- 最近1小时 ) WHERE elapsed_rank <= 20; SPOOL OFF EXIT EOF

8.2 使用Oracle Enterprise Manager

Oracle EM提供了图形化界面查看SQL执行情况:

  1. 访问EM控制台
  2. 导航到"Performance" -> "SQL Monitoring"
  3. 可以按资源消耗、执行时间等排序查看SQL

8.3 第三方监控工具

考虑使用专业的数据库监控工具如:

  • Oracle Cloud Control
  • SolarWinds Database Performance Analyzer
  • Quest Foglight for Oracle

9. 常见问题排查

9.1 查询返回空结果

可能原因及解决方案:

  1. 权限不足 - 确认用户有查询相关视图的权限
  2. 共享池已刷新 - 查询V$SQL只会显示当前共享池中的SQL
  3. 没有活跃SQL - 检查V$SESSION中确实有活跃会话

9.2 SQL文本被截断

Oracle中很多视图的SQL_TEXT列只显示前1000字符,要获取完整SQL:

SELECT sql_id, sql_fulltext FROM v$sql WHERE sql_id = '&sql_id';

9.3 历史SQL查询不到

如果AWR中查不到历史SQL,可能:

  1. SQL不在快照采集期间执行
  2. SQL资源消耗不够高,未被捕获
  3. AWR保留策略设置太短

检查AWR设置:

SELECT * FROM dba_hist_wr_control;

10. 最佳实践建议

  1. 定期收集基线:建立SQL性能基线,便于对比分析

    EXEC DBMS_WORKLOAD_REPOSITORY.create_baseline( start_snap_id => 100, end_snap_id => 110, baseline_name => 'Normal_Workload');
  2. 重点关注TOP SQL:定期分析资源消耗最高的SQL

  3. 使用SQL Plan Management:防止执行计划退化

    -- 捕获SQL计划基线 DECLARE l_plans_loaded PLS_INTEGER; BEGIN l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache( sql_id => '&sql_id'); END; /
  4. 合理设置AWR保留期:根据存储容量和需求调整

    EXEC DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings( retention => 21600, -- 单位:分钟(15天) interval => 60); -- 快照间隔(分钟)
  5. 建立自动化监控:设置阈值告警,及时发现性能问题

11. 高级技巧与经验分享

11.1 使用SQLHC进行健康检查

SQL Health Check (SQLHC)是Oracle提供的免费工具,可以深入分析SQL性能问题:

  1. 下载SQLHC脚本
  2. 针对特定SQL_ID运行:
    sqlhc.sql TARGET "sql_id=&sql_id"
  3. 分析生成的报告文件

11.2 使用DBMS_SQLTUNE捕获SQL

对于偶发但重要的SQL,可以主动捕获到SQL调优集:

-- 创建调优集 EXEC DBMS_SQLTUNE.create_sqlset( sqlset_name => 'Critical_SQL_Set', description => 'Captured critical SQL statements'); -- 从游标缓存加载SQL DECLARE l_cursor DBMS_SQLTUNE.sqlset_cursor; BEGIN OPEN l_cursor FOR SELECT VALUE(p) FROM TABLE(DBMS_SQLTUNE.select_cursor_cache( 'sql_id IN (''&sql_id1'',''&sql_id2'')', NULL, NULL, NULL, NULL, 1, NULL, 'ALL')) p; DBMS_SQLTUNE.load_sqlset( sqlset_name => 'Critical_SQL_Set', populate_cursor => l_cursor); END; / -- 分析调优集中的SQL SELECT dbms_sqltune.report_sql_detail( sql_id => '&sql_id', type => 'TEXT', level => 'ALL') as report FROM dual;

11.3 使用SQL Patch修复问题SQL

对于无法修改的应用SQL,可以使用SQL Patch临时修复:

-- 创建SQL Patch DECLARE l_patch_name VARCHAR2(30); BEGIN l_patch_name := DBMS_SQLDIAG.create_sql_patch( sql_id => '&sql_id', hint_text => 'INDEX(employees emp_dept_idx)', name => 'fix_sql_'||'&sql_id'); END; / -- 验证SQL Patch SELECT name, sql_text, status, created FROM dba_sql_patches WHERE sql_id = '&sql_id';

11.4 使用SQL Plan Baseline稳定性能

对于关键业务SQL,使用SPM稳定执行计划:

-- 手动加载计划基线 DECLARE l_plans_loaded PLS_INTEGER; BEGIN l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache( sql_id => '&sql_id', fixed => 'YES'); END; / -- 验证加载的计划 SELECT sql_handle, plan_name, enabled, accepted, fixed FROM dba_sql_plan_baselines WHERE sql_text LIKE '%&sql_text%';

12. 性能数据持久化方案

12.1 创建历史性能表

CREATE TABLE sql_performance_history ( capture_date DATE, sql_id VARCHAR2(13), executions NUMBER, elapsed_time NUMBER, cpu_time NUMBER, buffer_gets NUMBER, disk_reads NUMBER, sql_text CLOB, CONSTRAINT pk_sql_perf_hist PRIMARY KEY (capture_date, sql_id) ) TABLESPACE tools; CREATE INDEX idx_sql_perf_hist_sqlid ON sql_performance_history(sql_id);

12.2 定期捕获性能数据

BEGIN INSERT INTO sql_performance_history SELECT SYSDATE, sql_id, executions, elapsed_time, cpu_time, buffer_gets, disk_reads, (SELECT sql_fulltext FROM v$sql s WHERE s.sql_id = a.sql_id AND ROWNUM = 1) FROM v$sqlstats a WHERE executions > 0 AND last_active_time > SYSDATE - 1/24; -- 最近1小时 COMMIT; END; /

12.3 性能趋势分析

SELECT TRUNC(capture_date, 'HH') as hour, sql_id, SUM(executions) as executions, ROUND(SUM(elapsed_time)/1000000,2) as total_elapsed_sec, ROUND(SUM(elapsed_time)/1000000/NULLIF(SUM(executions),0),4) as avg_elapsed_sec, MAX(SUBSTR(sql_text,1,100)) as sql_text_sample FROM sql_performance_history WHERE capture_date > SYSDATE - 7 GROUP BY TRUNC(capture_date, 'HH'), sql_id HAVING SUM(executions) > 100 ORDER BY hour, total_elapsed_sec DESC;

13. 资源消耗分析与优化

13.1 识别高资源消耗模式

SELECT SUBSTR(sql_text,1,60) as sql_part, COUNT(*) as sql_count, SUM(executions) as total_executions, ROUND(SUM(elapsed_time)/1000000,2) as total_elapsed_sec, ROUND(SUM(buffer_gets)/NULLIF(SUM(executions),0)) as avg_buffer_gets, ROUND(SUM(disk_reads)/NULLIF(SUM(executions),0)) as avg_disk_reads FROM ( SELECT sql_id, executions, elapsed_time, buffer_gets, disk_reads, (SELECT sql_text FROM v$sql s WHERE s.sql_id = a.sql_id AND ROWNUM = 1) as sql_text FROM v$sqlstats a WHERE executions > 0 ) GROUP BY SUBSTR(sql_text,1,60) HAVING SUM(elapsed_time)/1000000 > 10 -- 总耗时超过10秒 ORDER BY total_elapsed_sec DESC;

13.2 I/O密集型SQL分析

SELECT sql_id, ROUND(disk_reads/NULLIF(executions,0)) as reads_per_exec, ROUND(buffer_gets/NULLIF(executions,0)) as gets_per_exec, ROUND(rows_processed/NULLIF(executions,0)) as rows_per_exec, SUBSTR(sql_text,1,100) as sql_text FROM ( SELECT s.sql_id, s.executions, s.disk_reads, s.buffer_gets, s.rows_processed, t.sql_text FROM v$sqlstats s JOIN v$sqltext_with_newlines t ON s.sql_id = t.sql_id WHERE t.piece = 0 AND s.executions > 0 ) WHERE disk_reads/NULLIF(executions,0) > 1000 -- 每次执行超过1000次物理读 ORDER BY reads_per_exec DESC;

13.3 CPU密集型SQL分析

SELECT sql_id, ROUND(cpu_time/NULLIF(executions,0)/1000) as cpu_ms_per_exec, ROUND(elapsed_time/NULLIF(executions,0)/1000) as elapsed_ms_per_exec, SUBSTR(sql_text,1,100) as sql_text FROM ( SELECT s.sql_id, s.executions, s.cpu_time, s.elapsed_time, t.sql_text FROM v$sqlstats s JOIN v$sqltext_with_newlines t ON s.sql_id = t.sql_id WHERE t.piece = 0 AND s.executions > 0 ) WHERE cpu_time/NULLIF(executions,0) > 100000 -- 每次执行CPU时间超过100ms ORDER BY cpu_ms_per_exec DESC;

14. 执行计划稳定性管理

14.1 执行计划对比分析

-- 获取SQL的所有子游标和执行计划 SELECT s.child_number, s.plan_hash_value, s.executions, s.buffer_gets, s.disk_reads, s.elapsed_time/1000000 as elapsed_sec, s.cpu_time/1000000 as cpu_sec FROM v$sql s WHERE s.sql_id = '&sql_id' ORDER BY s.child_number; -- 比较两个子游标的执行计划差异 SELECT * FROM TABLE(DBMS_XPLAN.compare_cursors( sql_id => '&sql_id', child_number1 => 0, child_number2 => 1, type => 'TEXT'));

14.2 执行计划历史分析

-- 查询AWR中的执行计划历史 SELECT snap_id, plan_hash_value, executions_delta as execs, ROUND(elapsed_time_delta/1000000/NULLIF(executions_delta,0),4) as avg_sec_per_exec, ROUND(buffer_gets_delta/NULLIF(executions_delta,0)) as avg_buffer_gets, ROUND(disk_reads_delta/NULLIF(executions_delta,0)) as avg_disk_reads FROM dba_hist_sqlstat WHERE sql_id = '&sql_id' AND executions_delta > 0 ORDER BY snap_id;

14.3 强制使用特定执行计划

-- 创建SQL Profile固定执行计划 DECLARE l_profile_name VARCHAR2(30); BEGIN l_profile_name := DBMS_SQLTUNE.accept_sql_profile( task_name => '&task_name', name => 'PROFILE_&sql_id', description => 'Profile for SQL_ID &sql_id', category => 'DEFAULT', force_match => TRUE); END; / -- 验证SQL Profile SELECT name, category, status, sql_text FROM dba_sql_profiles WHERE sql_text LIKE '%&sql_text%';

15. 自动化监控与告警

15.1 创建阈值告警

BEGIN DBMS_SERVER_ALERT.set_threshold( metrics_id => DBMS_SERVER_ALERT.elapsed_time_per_call, warning_operator => DBMS_SERVER_ALERT.operator_ge, warning_value => '0.5', -- 0.5秒 critical_operator => DBMS_SERVER_ALERT.operator_ge, critical_value => '1', -- 1秒 observation_period => 5, -- 5分钟 consecutive_occurrences => 3, -- 连续3次 instance_name => 'orcl', object_type => DBMS_SERVER_ALERT.object_type_service, object_name => 'SYS$USERS'); END; / -- 查看当前告警设置 SELECT metrics_name, warning_value, critical_value FROM dba_thresholds;

15.2 使用DBMS_SCHEDULER创建监控作业

BEGIN DBMS_SCHEDULER.create_job( job_name => 'MONITOR_HIGH_LOAD_SQL', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN INSERT INTO sql_performance_history SELECT SYSDATE, sql_id, executions, elapsed_time, cpu_time, buffer_gets, disk_reads, (SELECT sql_fulltext FROM v$sql s WHERE s.sql_id = a.sql_id AND ROWNUM = 1) FROM v$sqlstats a WHERE executions > 0 AND last_active_time > SYSDATE - 5/1440; -- 最近5分钟 COMMIT; END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=MINUTELY;INTERVAL=5', enabled => TRUE, comments => 'Job to monitor high load SQL every 5 minutes'); END; / -- 查看作业运行情况 SELECT job_name, enabled, last_start_date, next_run_date FROM user_scheduler_jobs;

16. 实战案例解析

16.1 案例一:突然性能下降

现象:某关键报表SQL平时运行很快,突然变慢。

排查步骤:

  1. 确认SQL_ID:

    SELECT sql_id, sql_text FROM v$sql WHERE sql_text LIKE '%报表关键SQL%';
  2. 检查执行计划变化:

    SELECT snap_id, plan_hash_value, executions_delta, elapsed_time_delta/1000000 as elapsed_sec FROM dba_hist_sqlstat WHERE sql_id = '&sql_id' ORDER BY snap_id DESC;
  3. 发现执行计划改变后,固定原计划:

    -- 从AWR加载好的执行计划到SPM DECLARE l_plans PLS_INTEGER; BEGIN l_plans := DBMS_SPM.load_plans_from_awr( begin_snap => &good_snap_id, end_snap => &good_snap_id + 1, basic_filter => 'sql_id = ''&sql_id'''); END; /

16.2 案例二:数据库整体变慢

现象:数据库响应变慢,AWR显示"SQL ordered by Elapsed Time"中有大量相似SQL。

排查步骤:

  1. 识别问题SQL模式:

    SELECT SUBSTR(sql_text,1,60), COUNT(*), SUM(elapsed_time)/1000000 FROM v$sqlstats GROUP BY SUBSTR(sql_text,1,60) ORDER BY 3 DESC;
  2. 发现是缺少绑定变量导致硬解析过多:

    SELECT force_matching_signature, COUNT(*) FROM v$sql GROUP BY force_matching_signature HAVING COUNT(*) > 20 ORDER BY 2 DESC;
  3. 解决方案:

    • 修改应用使用绑定变量
    • 临时设置cursor_sharing=FORCE

16.3 案例三:特定时段锁等待

现象:每天上午10点出现锁等待,会话堆积。

排查步骤:

  1. 创建ASH快照:

    EXEC DBMS_WORKLOAD_REPOSITORY.create_snapshot('ALL');
  2. 分析问题时段ASH数据:

    SELECT sample_time, event, COUNT(*) FROM dba_hist_active_sess_history WHERE sample_time BETWEEN TO_DATE('2023-01-01 09:50','YYYY-MM-DD HH24:MI') AND TO_DATE('2023-01-01 10:10','YYYY-MM-DD HH24:MI') GROUP BY sample_time, event ORDER BY sample_time, COUNT(*) DESC;
  3. 发现是某个批处理作业导致:

    • 调整作业调度时间
    • 优化批处理SQL

17. 工具与脚本推荐

17.1 SQLT (SQLT诊断工具)

SQLT是Oracle提供的强大诊断工具,可以深入分析SQL性能问题。

使用步骤:

  1. 从Oracle Support下载sqlt.zip
  2. 解压并运行安装脚本
  3. 针对问题SQL运行:
    sqlplus / as sysdba @sqlt/utl/sqlhc.sql TARGET "sql_id=&sql_id"

17.2 OraPlex工具集

OraPlex提供了一系列实用的SQL脚本:

  • ashtop.sql - 查询ASH中的TOP事件
  • sqlstat.sql - SQL执行统计信息
  • planx.sql - 执行计划对比工具

17.3 自定义监控脚本

建议DBA团队建立自己的脚本库,包含:

  • 实时监控脚本
  • 历史分析脚本
  • 性能比对脚本
  • 自动化报告脚本

18. 性能数据可视化

18.1 使用Oracle SQL Developer

Oracle SQL Developer提供了可视化工具分析SQL性能:

  1. 连接数据库
  2. 导航到"Tools" -> "Monitor SQL"
  3. 可以查看实时SQL执行情况
  4. 生成执行计划和统计信息图表

18.2 使用Grafana监控

搭建Grafana监控平台展示Oracle性能数据:

  1. 使用Prometheus或Telegraf采集Oracle指标
  2. 配置Grafana数据源
  3. 创建仪表盘展示:
    • SQL执行时间趋势
    • 资源消耗TOP SQL
    • 执行计划变化监控

18.3 自定义报表

使用SQL*Plus生成HTML报表:

SET MARKUP HTML ON SPOOL sql_report.html SELECT sql_id, executions, ROUND(elapsed_time/1000000,2) as elapsed_sec, ROUND(buffer_gets/NULLIF(executions,0)) as avg_buffer_gets, SUBSTR(sql_text,1,100) as sql_text FROM v$sqlstats WHERE executions > 0 ORDER BY elapsed_time DESC FETCH FIRST 20 ROWS ONLY; SPOOL OFF

19. 环境配置建议

19.1 初始化参数优化

-- 共享池大小 ALTER SYSTEM SET shared_pool_size=2G SCOPE=BOTH; -- 游标共享 ALTER SYSTEM SET cursor_sharing=EXACT SCOPE=SPFILE; -- AWR设置 EXEC DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings( interval => 30, retention => 43200);

19.2 统计信息收集策略

-- 自动统计信息收集 BEGIN DBMS_AUTO_TASK_ADMIN.enable( client_name => 'auto optimizer stats collection', operation => NULL, window_name => NULL); END; / -- 对象级统计信息设置 EXEC DBMS_STATS.set_table_prefs('SCOTT','EMP','ESTIMATE_PERCENT','DBMS_STATS.AUTO_SAMPLE_SIZE');

19.3 资源管理器配置

对于混合负载环境,使用Resource Manager限制报告类SQL:

BEGIN DBMS_RESOURCE_MANAGER.create_pending_area(); DBMS_RESOURCE_MANAGER.create_consumer_group( consumer_group => 'REPORT_GROUP', comment => 'Group for reporting queries'); DBMS_RESOURCE_MANAGER.create_plan( plan => 'DAYTIME_PLAN', comment => 'Plan for daytime operations'); DBMS_RESOURCE_MANAGER.create_plan_directive( plan => 'DAYTIME_PLAN', group_or_subplan => 'REPORT_GROUP', comment => 'Limit reporting queries', mgmt_p1 => 20, parallel_degree_limit_p1 => 4); DBMS_RESOURCE_MANAGER.submit_pending_area(); END; /

20. 总结与持续优化

在实际工作中,我发现建立一个完整的SQL性能监控体系非常重要。以下是我总结的几个关键点:

  1. 建立基线:记录正常情况下的SQL性能指标,便于对比分析
  2. 自动化监控:设置定期作业捕获性能数据,避免问题发生后无从排查
  3. 分层分析:
    • 实时视图用于紧急问题排查
    • AWR用于趋势分析
    • SQL Tuning工具用于深度优化
  4. 知识积累:建立团队知识库,记录常见问题和解法

最后分享一个实用技巧:对于复杂的性能问题,可以同时收集以下数据做关联分析:

  • AWR报告
  • ASH数据
  • SQL Monitor报告
  • 10046 trace
  • 系统级别监控数据(CPU、I/O等)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询