Oracle SQLT 工具包实战:SQL 性能诊断与执行计划突变定位
简介这份资源是面向Oracle DBA、系统管理员及数据库性能调优开发者的SQLT工具脚本合集聚焦10g至19c多版本数据库的SQL语句分析与执行计划优化。压缩包共收录205个文件以160个sql脚本为主体辅以19个pkb与19个pks包体文件、5个txt说明及2个html文档整体约927KB结构紧凑便于按模块查阅。其中coe_xfr_sql_profile.sql等脚本可用于SQL Profile的迁移与共享配合SQL Tuning Advisor生成的优化建议帮助读者在开发、测试与生产环境间转移执行策略减少SQL执行时间与资源消耗。内容还涉及SQLT的检查、分析与报告生成流程适合需要排查执行计划劣化、提升数据库稳定性的中高级技术人员参考。目前已有417人学习下载可作为多版本Oracle环境下SQL性能调优的实用脚本工具集。1. 从一份 2020 年的 SQLT 工具包说起Oracle 性能诊断的“黑匣子”到底怎么用如果你在 Oracle 一线待过大概率遇到过这种场景业务反馈某条 SQL 突然变慢AWR 报告里 Top SQL 看着都正常执行计划也没明显变化但就是慢。这时候老 DBA 往往会甩出一个词——SQLT。这份sqlt_10g_11g_12c_18c_19c_5th_June_2020.zip就是 SQLTSQLTXPLAIN在 2020 年 6 月发布的版本覆盖 10g 到 19c 五个大版本。它不是普通脚本合集而是 Oracle 官方支持体系里用来“取证”的重型工具把一条 SQL 的执行计划、统计信息、绑定变量、优化器环境、对象元数据全部打包成一个诊断文件交给 MOS 或内部专家分析。适合谁适合被 SQL 性能问题反复折磨、又不想每次都靠猜的 DBA 和开发。下面我从这份资源的结构、安装、采集、排错到进阶技巧按我实际拆包和跑过的路径讲一遍。2. 拆开压缩包目录结构、版本适配与安装前的环境核对2.1 压缩包里的五个版本目录到底怎么选解压后你会看到按数据库版本分层的目录常见结构是sqlt_10g、sqlt_11g、sqlt_12c、sqlt_18c、sqlt_19c每个目录下再分install、run、uninstall等子目录。选错版本不会直接报错但采集出来的诊断文件可能缺字段尤其是 12c 之后优化器统计信息、自适应执行计划、SQL 计划基线这些内容10g 版本的脚本根本不会去抓。我一般按目标库的v$version主版本号选比如 19c 库就用sqlt_19c不要图省事拿 11g 的脚本去跑 19c。跨版本兼容性在 SQLT 里是“向下能跑、向上不全”这是血泪经验。2.2 安装前必须确认的四个环境参数安装 SQLT 不是解压完就能跑先连到目标库执行下面这段检查。它确认表空间、权限、字符集和优化器参数缺一个后面采集就可能中断。-- 检查当前用户权限和表空间 select username, default_tablespace, temporary_tablespace from user_users; -- 确认是否有创建对象和访问数据字典的权限 select privilege from user_sys_privs where privilege in (CREATE TABLE,CREATE PROCEDURE,CREATE TYPE,SELECT ANY DICTIONARY); -- 查看字符集避免诊断文件乱码 select value from nls_database_parameters where parameter NLS_CHARACTERSET; -- 确认优化器相关参数SQLT 会记录这些 select name, value from v$parameter where name in (optimizer_mode,optimizer_features_enable,statistics_level);逻辑说明第一段确认用户默认表空间SQLT 会在里面建SQLTXPLAIN用户和一堆临时对象第二段确认权限缺少SELECT ANY DICTIONARY会导致采集时读不到DBA_视图第三段字符集影响生成的 HTML 报告可读性第四段优化器参数是诊断 SQL 执行计划差异的关键上下文。参数怎么改如果权限不足让 DBA 授权表空间建议单独给 SQLT 建一个别和业务表混用否则采集大 SQL 时可能把业务表空间撑满。2.3 安装脚本的执行顺序与常见返回码进入对应版本目录的install子目录用 SQL*Plus 以 SYSDBA 或具备权限的用户执行主安装脚本。常见做法是cd sqlt_19c/install sqlplus / as sysdba sqlt_install.sql执行过程中会提示输入 SQLT 用户的密码、默认表空间、临时表空间。安装完成后脚本会输出一段确认信息并生成sqlt_install.log。如果看到ORA-00955表示对象已存在通常是之前装过没卸干净ORA-01950是表空间配额问题ORA-01031是权限不足。我一般装完立刻跑一次sqlt_health_check.sql部分版本叫sqlt_healthcheck.sql确认核心包和视图都有效。3. 采集一条问题 SQL从 XTRACT 到诊断文件落地的完整操作3.1 用 XTRACT 方法抓取单条 SQL 的完整诊断集SQLT 最常用的采集方式是 XTRACT针对一条具体 SQL_ID 或 SQL 文本。假设业务反馈sql_id abc123xyz的语句变慢先确认它还在共享池里select sql_id, child_number, plan_hash_value, executions, elapsed_time/1000000 as elapsed_sec from v$sql where sql_id abc123xyz;如果v$sql里已经找不到说明游标被挤出去了这时候要么从 AWR 历史里拿要么让业务重新跑一次再抓。确认存在后执行 XTRACT-- 以 SQLT 用户连接后执行 sqlt/run/sqltxtract.sql abc123xyz脚本会提示选择采集范围一般选默认的COMPLETE。采集过程从几十秒到几分钟不等取决于 SQL 涉及的对象数量和统计信息量。完成后会在当前目录生成一个.zip文件命名类似sqlt_s12345_abc123xyz.zip。这个 zip 就是可以上传到 MOS 或内部专家分析的诊断包。3.2 采集参数怎么调三个影响诊断深度的开关XTRACT 有几个关键参数默认值不一定适合所有场景。常见做法是在执行前用define设置define SQLT_TOOL XTRACT define SQLT_DAYS 30 -- AWR 历史回溯天数 define SQLT_INCLUDE_STATS Y -- 是否包含统计信息 define SQLT_INCLUDE_PLAN Y -- 是否包含执行计划历史 sqlt/run/sqltxtract.sql abc123xyzSQLT_DAYS控制从 AWR 里捞多久的历史执行计划默认 30 天如果问题发生在更早要调大SQLT_INCLUDE_STATS决定是否导出表和索引的统计信息关掉能加快采集但会丢失诊断依据SQLT_INCLUDE_PLAN抓DBA_HIST_SQL_PLAN里的历史计划对分析计划突变非常关键。我一般全开除非 SQL 涉及的对象特别多导致采集超时。3.3 诊断文件里到底有什么核心报告文件清单生成的 zip 解压后是一堆 HTML 和文本文件新手容易看花眼。下面这张表列出最该先看的几个文件名内容用途sqlt_main.html主报告入口汇总 SQL 文本、执行计划、统计信息sqlt_plan.html执行计划详情对比不同 child cursor 的计划差异sqlt_stats.html优化器统计信息看表、索引、列统计是否过期sqlt_tcb.html目标 SQL 的 10053 跟踪优化器成本计算过程sqlt_bv.html绑定变量信息检查绑定变量窥探和直方图影响先看sqlt_main.html里的执行计划部分再对照sqlt_stats.html确认统计信息新鲜度最后用sqlt_tcb.html看优化器为什么选了这个计划。这套顺序能覆盖大部分“计划没变但变慢”的玄学问题。4. 避坑与排查SQLT 采集失败的五个典型现场4.1 ORA-20001 或采集脚本中途退出现象执行sqltxtract.sql后报ORA-20001或直接无输出退出。原因最常见的是 SQLT 用户缺少对目标 SQL 涉及对象的访问权限或者目标 SQL 引用了其他 schema 的表而当前用户没有SELECT ANY TABLE。解决用 SYSDBA 授予SELECT ANY DICTIONARY和SELECT ANY TABLE或者让 SQLT 用户对具体对象有读权限。如果还不行检查sqlt_install.log里是否有包编译错误。4.2 生成的 zip 文件异常小或为空现象采集完成但 zip 只有几 KB解压后报告内容缺失。原因目标 SQL 在采集瞬间已经从共享池老化或者SQLT_DAYS设得太小导致 AWR 里也没捞到。解决先确认v$sql里 SQL 还在如果不在就调大SQLT_DAYS从历史抓或者让业务重新执行一次并保持游标。另一个可能是临时表空间不足采集中间写临时表失败但脚本没报错。4.3 报告里执行计划显示为“PLAN NOT AVAILABLE”现象sqlt_plan.html里计划为空。原因SQL 使用了绑定变量且游标未硬解析或者采集时没有抓V$SQL_PLAN。解决确认采集参数SQLT_INCLUDE_PLANY并且目标 SQL 在v$sql里有对应的child_number。如果 SQL 是 PDML 或并行执行还要检查V$SQL_PLAN是否被快速老化。4.4 安装时 ORA-00942 表或视图不存在现象安装脚本执行到一半报ORA-00942。原因安装用户权限不够或者数据库版本与 SQLT 目录不匹配。比如拿 19c 的脚本装到 11g 库上某些DBA_视图在 11g 里不存在。解决严格按版本选目录安装用户用 SYSDBA 或至少有DBA角色。如果必须跨版本先看install目录下的readme确认最低版本要求。4.5 采集大 SQL 时数据库性能明显下降现象采集期间业务反馈数据库变慢。原因SQLT 会查询大量数据字典和 AWR 视图如果目标 SQL 涉及分区表或大量对象查询本身可能消耗较多资源。解决避开业务高峰采集或者用SQLT_INCLUDE_STATSN减少统计信息导出。另外可以限制SQLT_DAYS减少 AWR 扫描量。我一般会在采集前看一眼当前活跃会话数超过平时两倍就等一等。5. 进阶用法用 SQLT 对比两次采集定位计划突变的根因5.1 两次采集的 diff 方法SQLT 本身不直接提供 diff 命令但生成的报告是结构化 HTML我一般用文本对比工具处理关键文件。更实用的做法是对同一条 SQL 在“正常时”和“变慢时”各采集一次然后重点对比sqlt_plan.html里的Plan Hash Value、sqlt_stats.html里的LAST_ANALYZED和NUM_ROWS、以及sqlt_bv.html里的绑定变量值。下面这段 SQL 可以从两次采集的文本导出里快速比对统计信息-- 在 SQLT 用户下查询两次采集的统计信息快照 select c.sql_id, c.plan_hash_value, s.table_name, s.num_rows, s.last_analyzed from sqlt_collect c join sqlt_stats_snapshot s on c.snap_id s.snap_id where c.sql_id abc123xyz order by c.snap_id, s.table_name;逻辑说明sqlt_collect和sqlt_stats_snapshot是 SQLT 安装后生成的元数据表具体表名因版本略有差异常见为SQLTXPLAINschema 下的SQLT$开头表。这条查询把两次采集的计划哈希和统计信息并列能一眼看出是统计信息过期还是计划本身变了。参数上sql_id换成你的目标 SQLsnap_id对应采集批次。5.2 结合 10053 跟踪看优化器决策sqlt_tcb.html里其实是 10053 事件的输出。如果你要更细的优化器成本计算可以在采集前手动开 10053alter session set events 10053 trace name context forever, level 1; -- 执行目标 SQL alter session set events 10053 trace name context off;生成的 trace 文件在user_dump_dest下配合 SQLT 报告一起看能定位到优化器为什么选了错误的索引或连接方式。我一般只在 SQLT 报告里看到“成本异常”时才开 10053因为 trace 文件很大读起来费劲。5.3 一个我常用的验证习惯每次用 SQLT 定位到问题并调整后我会强制再采集一次对比调整前后的Plan Hash Value和Elapsed Time。如果计划哈希没变但执行时间降了说明问题在统计信息或绑定变量如果计划哈希变了说明优化器选了新路径。从那以后我每次处理 SQL 性能问题都强制走一遍“采集—对比—验证”的闭环不再靠单次 AWR 报告下结论。希望帮到你。本文还有配套的精品资源点击获取