Skip to content

Oracle SQL级别指标

执行时间指标

响应时间

  • 总执行时间:SELECT elapsed_time/1000000 "Seconds" FROM v$sql WHERE sql_id = 'sql_id';
  • CPU 时间:SELECT cpu_time/1000000 "Seconds" FROM v$sql WHERE sql_id = 'sql_id';
  • 等待时间:SELECT (elapsed_time - cpu_time)/1000000 "Seconds" FROM v$sql WHERE sql_id = 'sql_id';

执行频率

  • 执行次数:SELECT executions FROM v$sql WHERE sql_id = 'sql_id';
  • 平均执行时间:SELECT (elapsed_time/executions)/1000000 "Avg Seconds" FROM v$sql WHERE sql_id = 'sql_id' AND executions > 0;
  • 每分钟执行次数:SELECT executions/(elapsed_time/1000000/60) "Executions Per Minute" FROM v$sql WHERE sql_id = 'sql_id' AND elapsed_time > 0;

时间分布

  • 解析时间:SELECT parse_time/1000000 "Seconds" FROM v$sql WHERE sql_id = 'sql_id';
  • 优化时间:SELECT optimizer_cost FROM v$sql WHERE sql_id = 'sql_id';
  • 执行时间:SELECT (elapsed_time - parse_time)/1000000 "Seconds" FROM v$sql WHERE sql_id = 'sql_id';

资源消耗指标

I/O 消耗

  • 逻辑读:SELECT buffer_gets FROM v$sql WHERE sql_id = 'sql_id';
  • 物理读:SELECT disk_reads FROM v$sql WHERE sql_id = 'sql_id';
  • 直接读:SELECT direct_reads FROM v$sql WHERE sql_id = 'sql_id';
  • 直接写:SELECT direct_writes FROM v$sql WHERE sql_id = 'sql_id';
  • 平均逻辑读:SELECT buffer_gets/executions "Avg Buffer Gets" FROM v$sql WHERE sql_id = 'sql_id' AND executions > 0;

内存消耗

  • 共享池使用:SELECT sharable_mem FROM v$sql WHERE sql_id = 'sql_id';
  • 持久内存使用:SELECT persistent_mem FROM v$sql WHERE sql_id = 'sql_id';
  • 运行时内存使用:SELECT runtime_mem FROM v$sql WHERE sql_id = 'sql_id';

网络消耗

  • 行处理数:SELECT rows_processed FROM v$sql WHERE sql_id = 'sql_id';
  • 平均每行处理时间:SELECT (elapsed_time/rows_processed)/1000000 "Avg Seconds Per Row" FROM v$sql WHERE sql_id = 'sql_id' AND rows_processed > 0;
  • 平均每行逻辑读:SELECT buffer_gets/rows_processed "Avg Buffer Gets Per Row" FROM v$sql WHERE sql_id = 'sql_id' AND rows_processed > 0;

执行计划指标

执行计划成本

  • 优化器成本:SELECT optimizer_cost FROM v$sql WHERE sql_id = 'sql_id';
  • 实际行数:SELECT rows_processed FROM v$sql WHERE sql_id = 'sql_id';
  • 估计行数:通过执行计划查看
  • 行数差异:实际行数与估计行数的差异

执行计划操作

  • 全表扫描:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' AND operation = 'TABLE ACCESS' AND options = 'FULL';
  • 索引扫描:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' AND operation = 'INDEX';
  • 嵌套循环:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' AND operation = 'NESTED LOOPS';
  • 哈希连接:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' AND operation = 'HASH JOIN';
  • 排序操作:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' AND operation = 'SORT';

执行计划稳定性

  • 执行计划变更:监控 SQL 语句的执行计划是否发生变化
  • 绑定变量窥视:SELECT * FROM v$sql WHERE sql_id = 'sql_id' AND bind_data IS NOT NULL;
  • 统计信息影响:检查统计信息变更对执行计划的影响

等待事件指标

主要等待事件

  • 查看等待事件:SELECT event, total_waits, time_waited FROM v$sql_metrics WHERE sql_id = 'sql_id';
  • 等待事件占比:分析各种等待事件的占比
  • 主要等待原因:识别 SQL 语句的主要等待原因

常见等待事件

  • I/O 等待:db file sequential read, db file scattered read
  • 锁等待:enqueue, row lock contention
  • 缓冲区等待:buffer busy waits, free buffer waits
  • 并发等待:latch free, mutex contention
  • 网络等待:SQL*Net message from client, SQL*Net message to client

等待事件分析

  • 等待时间分析:SELECT event, time_waited FROM v$sql_metrics WHERE sql_id = 'sql_id' ORDER BY time_waited DESC;
  • 等待次数分析:SELECT event, total_waits FROM v$sql_metrics WHERE sql_id = 'sql_id' ORDER BY total_waits DESC;
  • 平均等待时间:SELECT event, time_waited/total_waits "Avg Wait Time" FROM v$sql_metrics WHERE sql_id = 'sql_id' AND total_waits > 0 ORDER BY "Avg Wait Time" DESC;

统计信息指标

表统计信息

  • 表行数:SELECT num_rows FROM dba_tables WHERE table_name = 'TABLE_NAME';
  • 表块数:SELECT blocks FROM dba_tables WHERE table_name = 'TABLE_NAME';
  • 平均行长度:SELECT avg_row_len FROM dba_tables WHERE table_name = 'TABLE_NAME';

索引统计信息

  • 索引高度:SELECT blevel FROM dba_indexes WHERE index_name = 'INDEX_NAME';
  • 索引叶子块:SELECT leaf_blocks FROM dba_indexes WHERE index_name = 'INDEX_NAME';
  • 索引区分度:SELECT distinct_keys FROM dba_indexes WHERE index_name = 'INDEX_NAME';

统计信息新鲜度

  • 统计信息收集时间:SELECT last_analyzed FROM dba_tables WHERE table_name = 'TABLE_NAME';
  • 数据变更率:分析表数据的变更情况
  • 统计信息是否过时:根据数据变更率判断

SQL 性能监控

实时监控

  • 活动 SQL 监控:EXECUTE DBMS_SQLTUNE.CREATE_SQL_SET('sqlset_name');
  • 查看活动 SQL:SELECT * FROM v$active_session_history WHERE sql_id = 'sql_id';
  • 实时执行计划:SELECT * FROM v$sql_plan_monitor WHERE sql_id = 'sql_id';

历史监控

  • AWR 报告:@$ORACLE_HOME/rdbms/admin/awrrpt.sql
  • SQL 性能分析器:EXECUTE DBMS_SQLPA.ANALYZE_SQL_SET;
  • 历史执行计划:SELECT * FROM dba_hist_sql_plan WHERE sql_id = 'sql_id';

自动性能诊断

  • ADDM 报告:@$ORACLE_HOME/rdbms/admin/addmrpt.sql
  • SQL 调优顾问:EXECUTE DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => 'sql_id');
  • 自动 SQL 优化:EXECUTE DBMS_AUTO_SQLTUNE.EXECUTE_TUNING_TASK;

SQL 级别指标的使用

性能问题识别

  • 识别高负载 SQL:SELECT sql_id, elapsed_time, buffer_gets FROM v$sql ORDER BY elapsed_time DESC;
  • 识别 I/O 密集型 SQL:SELECT sql_id, disk_reads FROM v$sql ORDER BY disk_reads DESC;
  • 识别 CPU 密集型 SQL:SELECT sql_id, cpu_time FROM v$sql ORDER BY cpu_time DESC;
  • 识别执行频率高的 SQL:SELECT sql_id, executions FROM v$sql ORDER BY executions DESC;

性能瓶颈分析

  • 分析执行计划:EXPLAIN PLAN FOR SELECT * FROM table_name; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
  • 分析等待事件:SELECT event, time_waited FROM v$sql_metrics WHERE sql_id = 'sql_id' ORDER BY time_waited DESC;
  • 分析资源消耗:SELECT buffer_gets, disk_reads, cpu_time FROM v$sql WHERE sql_id = 'sql_id';

性能优化建议

  • 索引优化:添加或修改索引
  • SQL 重写:优化 SQL 语句结构
  • 执行计划调整:使用提示或修改统计信息
  • 分区优化:使用分区表减少数据扫描范围
  • 并行执行:对于大型查询使用并行执行

常见问题(FAQ)

Q1: 如何识别性能最差的 SQL 语句?

A1: 可以通过以下方法识别性能最差的 SQL 语句:

  • 按执行时间排序:SELECT sql_id, sql_text, elapsed_time/1000000 "Seconds", executions FROM v$sql ORDER BY elapsed_time DESC FETCH FIRST 10 ROWS ONLY;
  • 按逻辑读排序:SELECT sql_id, sql_text, buffer_gets, executions FROM v$sql ORDER BY buffer_gets DESC FETCH FIRST 10 ROWS ONLY;
  • 按物理读排序:SELECT sql_id, sql_text, disk_reads, executions FROM v$sql ORDER BY disk_reads DESC FETCH FIRST 10 ROWS ONLY;
  • 按平均执行时间排序:SELECT sql_id, sql_text, (elapsed_time/executions)/1000000 "Avg Seconds", executions FROM v$sql WHERE executions > 0 ORDER BY "Avg Seconds" DESC FETCH FIRST 10 ROWS ONLY;

Q2: 如何分析 SQL 语句的执行计划?

A2: 分析 SQL 语句的执行计划可以通过以下方法:

  • 使用 EXPLAIN PLAN:EXPLAIN PLAN FOR SELECT * FROM table_name WHERE condition; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
  • 使用 V$SQL_PLAN:SELECT * FROM v$sql_plan WHERE sql_id = 'sql_id' ORDER BY id;
  • 使用 DBMS_XPLAN.DISPLAY_CURSOR:SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id'));
  • 使用 Oracle Enterprise Manager:通过 OEM 界面查看执行计划
  • 分析执行计划操作:识别全表扫描、索引扫描、连接操作等
  • 分析执行计划成本:评估优化器成本是否合理

Q3: 如何优化高 I/O 消耗的 SQL 语句?

A3: 优化高 I/O 消耗的 SQL 语句可以通过以下方法:

  • 添加或修改索引:减少物理读和逻辑读
  • 使用分区表:只扫描相关分区的数据
  • 优化 SQL 语句:减少不必要的列和行
  • 使用物化视图:对于复杂查询使用物化视图
  • 调整执行计划:使用提示或修改统计信息
  • 增加缓冲区缓存:提高数据缓存命中率
  • 优化存储系统:提高 I/O 子系统性能

Q4: 如何监控 SQL 语句的执行频率和响应时间?

A4: 监控 SQL 语句的执行频率和响应时间可以通过以下方法:

  • 使用 V$SQL 视图:SELECT sql_id, sql_text, executions, (elapsed_time/executions)/1000000 "Avg Response Time" FROM v$sql WHERE executions > 0 ORDER BY executions DESC;
  • 使用 AWR 报告:查看 Top SQL 部分
  • 使用 SQL 监控:EXECUTE DBMS_SQLTUNE.CREATE_SQL_SET('frequent_sql');
  • 使用自定义监控脚本:定期收集 SQL 执行统计信息
  • 设置阈值告警:当 SQL 执行时间超过阈值时告警

Q5: 如何判断 SQL 语句的性能是否正常?

A5: 判断 SQL 语句的性能是否正常可以通过以下方法:

  • 与历史性能比较:分析 SQL 语句的历史执行时间
  • 与预期性能比较:根据业务需求评估性能是否满足
  • 与同类 SQL 比较:与相似功能的 SQL 语句性能比较
  • 分析资源消耗:评估 CPU、I/O 等资源消耗是否合理
  • 分析执行计划:检查执行计划是否最优
  • 分析等待事件:识别是否存在异常等待事件
  • 使用基准测试:建立性能基准,定期比较