sql profile 是oracle优化器提示的持久化集合,非可执行脚本;需sql文本完全一致且状态为enabled才生效,force_match=>true可放宽字面量匹配但需人工核对。
sql tuning advisor 生成的 profile 是什么,能不能直接用
它不是可执行的 sql 脚本,而是一组优化器提示(hints)的集合,以 sql profile 形式持久化在数据字典中。oracle 会在语句硬解析时自动匹配并注入这些 hints,从而改变执行计划——但前提是语句文本完全一致(包括空格、大小写、绑定变量名),且 sql profile 处于 enabled 状态。
常见错误现象:DBMS_SQLTUNE.ACCEPT_SQL_PROFILE 执行成功,但原 SQL 执行计划没变。原因通常是:SQL 文本有细微差异(比如 AWR 报告里截断了部分字段名)、force_match => TRUE 没设、或者目标 SQL 正在使用其他 hint/outline/profile 冲突。
- 务必检查
DBA_SQL_PROFILES中该 profile 的STATUS和FORCE_MATCH值 - 用
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE(...))验证是否生效,别只看EXPLAIN PLAN FOR - 如果原 SQL 含绑定变量,建议显式设置
force_match => TRUE,否则 profile 只匹配字面量完全相同的语句
ACCEPT_SQL_PROFILE 的关键参数怎么选
DBMS_SQLTUNE.ACCEPT_SQL_PROFILE 有三个影响行为的核心参数:task_name、name、force_match。其中 force_match 最容易被忽略,但它直接决定 profile 的复用范围。
-
task_name必须来自DBMS_SQLTUNE.CREATE_TUNING_TASK或 AWR 自动任务,不能手写;查DBA_ADVISOR_LOG确认状态是COMPLETED -
name是 profile 名称,建议带业务标识(如'ORDERS_JOIN_OPT_2024Q3'),避免默认名prof_12345后续无法追溯 -
force_match => TRUE会让 Oracle 忽略字面量差异,按语法结构匹配 SQL;但代价是可能误匹配到语义不同的语句,需结合DBA_SQL_PROFILES的SQL_TEXT字段人工核对
为什么 profile 生效后性能反而更差
SQL Tuning Advisor 基于采样和模型估算生成建议,不保证在所有负载下都优于原计划。尤其当 SQL 涉及动态谓词、数据倾斜或并发修改时,profile 强制的执行路径可能放大锁争用或 buffer busy waits。
典型场景:profile 推荐使用 INDEX RANGE SCAN,但实际运行时因谓词选择率突变,导致大量逻辑读;或 profile 绑定了某个特定的 OPTIMIZER_FEATURES_ENABLE 版本,升级数据库后失效。
- 启用前先用
DBMS_SQLTUNE.EXECUTE_TUNING_TASK查看完整报告,重点关注 “Estimated Benefit” 是否 > 30%,低于这个值慎接 - 接受后立即在测试环境跑真实业务流量(非单次
EXPLAIN),监控v$sql_plan_statistics_all中的buffer_gets和elapsed_time - profile 不会自动随统计信息更新而调整,如果表数据量增长 5 倍以上,需重新跑 tuning task 并评估是否替换旧 profile
如何安全地回退已接受的 profile
没有“撤销接受”的 API,只能禁用或删除。但直接 DROP 有风险:如果多个 SQL 共享同一个 profile(通过 force_match),删掉会影响其他语句。
- 首选
DBMS_SQLTUNE.ALTER_SQL_PROFILE将STATUS改为DISABLED,这样原 SQL 会退回到默认优化器行为,且操作可逆 - 确认无其他 SQL 依赖该 profile 后,再用
DBMS_SQLTUNE.DROP_SQL_PROFILE彻底删除 - 删除后记得清空共享池中相关游标:
ALTER SYSTEM FLUSH SHARED_POOL或更精准地用DBMS_SHARED_POOL.PURGE清理具体ADDRESS和HASH_VALUE
profile 的匹配逻辑藏在优化器内部,不暴露给 DBA;哪怕你改了 SQL 注释或加了个空行,都可能导致 profile 失效——这点在应用发布前后特别容易翻车。










