恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
SQL突然变慢?用Oracle执行计划与SQL_ID识破绑定变量“多重人格”,配TaoToken排查
首页
资讯中心
/
SQL突然变慢?用Oracle执行计划与SQL_ID识破绑定变量“多重人格”,配TaoToken排查
SQL突然变慢?用Oracle执行计划与SQL_ID识破绑定变量“多重人格”,配TaoToken排查
发布时间:2026/9/28 19:28:00
1. 同一条 SQL 为什么会有“多重人格”线上告警最让人抓狂的一种情况同一条 SQL白天跑 200ms晚上跑 8s第二天早上又恢复正常。你去看 SQL 文本一个字都没变你去看索引也没人动过。但V$SQL里这条语句挂着好几个子游标每个子游标对应一个不同的PLAN_HASH_VALUE执行次数和耗时天差地别。这就是 Oracle 里典型的“绑定变量窥探Bind Peeking 自适应游标共享Adaptive Cursor Sharing”组合拳带来的副作用。简单说优化器第一次硬解析时偷看了绑定变量的值按那个值选了一个计划后面换了绑定变量值如果 ACS 判定“这个值可能适合另一个计划”就会再生成一个子游标。于是同一个SQL_ID下出现多个执行计划快的快死、慢的慢死。适合谁看日常要盯 Oracle 性能的 DBA、后端开发、运维同学。你需要会基本的 SQL*Plus 或 SQL Developer 操作能查V$SQL、V$SQL_PLAN这类动态性能视图。这篇会给出可直接复制的 SQL_ID 定位语句、执行计划对比方法、绑定变量捕获配置以及用 TaoToken 统一 Key 接入 AI 工具辅助分析执行计划文本的完整流程。我试过在一条统计类 SQL 上踩坑SQL_ID固定但CHILD_NUMBER从 0 涨到 5BUFFER_GETS从几百飙到几十万。下面按“定位 → 对比 → 捕获 → 修复 → 验证”的顺序走一遍。2. 前置准备TaoToken 统一 Key 与 API 通道排查执行计划时经常需要把DBMS_XPLAN输出、AWR 报告片段丢给 AI 工具做结构化解读比如“这个 HASH JOIN 为什么比 NESTED LOOPS 慢”“哪个步骤的 Cardinality 估算偏差最大”。如果每个 AI 工具都单独配 Key、单独改 base_url切换成本很高。TaoToken 的作用就是提供一个统一的 API 通道和 Key 管理入口让模型对话、编码辅助、Agent 类工具走同一套接入方式。你需要先拿到一个可用的 Key。打开官网注册后进入控制台在 API Keys 页面创建一个新 Key复制保存。注意 Key 只在创建时完整显示一次丢了就重新建。官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content控制台 / API Keyshttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_campaignrewrite接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_campaignrewriteAPI 基地址不带 UTMhttps://taotoken.net/api注意API 地址填https://taotoken.net/api不要自己拼/v1之外的路径具体以接入文档为准。Key 属于敏感凭证不要写进代码仓库或贴到公开聊天里。如果你只是临时验证模型能不能正确解读执行计划用模型对话页面最省事如果要把 AI 分析嵌进日常编码/脚本流程走 Coding Plan 更合适。下面第 3 节先给 Oracle 侧的排查配置第 4 节再给 TaoToken 侧的调用验证。3. 可复制配置定位多计划 SQL 与捕获绑定变量3.1 找出“一人多面”的 SQL_ID第一步永远是先确认这条 SQL 到底有几个计划。下面这条语句按PLAN_COUNT倒序把多计划 SQL 排前面同时算出平均耗时区间方便你判断“快慢差异”有多大。set linesize 400; col sql_text_sample for a120; SELECT sql_id, COUNT(DISTINCT plan_hash_value) AS plan_count, COUNT(DISTINCT child_number) AS child_count, SUM(executions) AS total_executions, MIN(ROUND(elapsed_time / NULLIF(executions,0) / 1000000, 4)) AS min_avg_sec, MAX(ROUND(elapsed_time / NULLIF(executions,0) / 1000000, 4)) AS max_avg_sec, SUBSTR((SELECT sql_text FROM v$sqltext_with_newlines WHERE sql_id v.sql_id AND piece 0), 1, 120) AS sql_text_sample FROM v$sql v WHERE executions 0 AND plan_hash_value 0 GROUP BY sql_id HAVING COUNT(DISTINCT plan_hash_value) 1 ORDER BY plan_count DESC, max_avg_sec DESC;预期结果你会看到类似g07bjs22tcg72这样的SQL_IDplan_count2、child_count3min_avg_sec0.0003、max_avg_sec1.2。快慢差三个数量级基本可以锁定问题。3.2 查看某个 SQL_ID 下所有子游标的“体检表”拿到SQL_ID后看每个子游标的执行次数、逻辑读、是否绑定敏感。SELECT child_number, plan_hash_value, executions, buffer_gets, disk_reads, rows_processed, is_bind_sensitive, is_bind_aware FROM v$sql WHERE sql_id g07bjs22tcg72 ORDER BY child_number;IS_BIND_SENSITIVEY说明这个游标对绑定变量值敏感IS_BIND_AWAREY说明 ACS 已经为它启用了多计划能力。这两个字段是判断“是不是绑定变量窥探惹的祸”的关键。3.3 逐个对比执行计划SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(g07bjs22tcg72, 0)); SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(g07bjs22tcg72, 1));重点看三处Plan hash value是否不同、Cost (%CPU)差多少、Rows估算行数和实际A-Rows如果开了STATISTICS_LEVELALL偏差多大。常见现象是慢计划里出现了TABLE ACCESS FULL而快计划走的是INDEX RANGE SCAN。3.4 捕获绑定变量真实值光看计划不够还要知道当时传了什么值。开启绑定变量捕获ALTER SYSTEM SET _optimizer_capture_sql_plan_baselines TRUE; -- 或者用更通用的方式先确认捕获视图可用 SELECT name, value FROM v$parameter WHERE name LIKE %bind%;更直接的是查V$SQL_BIND_CAPTURESELECT sql_id, name, position, datatype_string, value_string, last_captured FROM v$sql_bind_capture WHERE sql_id g07bjs22tcg72 ORDER BY position;如果这里查不到值说明捕获没开或已被刷出。可以在会话级临时开启ALTER SESSION SET events 10046 trace name context forever, level 4;注意10046级别 4 会记录绑定变量但 trace 文件增长快排查完记得关掉别长期开着。3.5 用 TaoToken 接入 AI 辅助解读计划把上面DBMS_XPLAN的输出复制出来通过 TaoToken 的 API 通道发给模型让它帮你标出“估算行数偏差最大的步骤”和“可能的修复方向”。下面是一个最小可用的 curl 示例Key 用你自己的替换。curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: claude-sonnet-4-20250514, messages: [ {role: system, content: 你是 Oracle 性能优化专家只输出执行计划中估算偏差最大的步骤和修复建议。}, {role: user, content: SQL_ID g07bjs22tcg72 child 1 的计划如下\n| Id | Operation | Name | Rows | Cost |\n| 0 | SELECT STATEMENT | | | 28 |\n| 5 | HASH JOIN | | 2 | 21 |\n请指出问题。} ] }如果你更习惯在对话界面里贴长文本直接用模型对话入口https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_campaignrewrite4. 验证请求与成功结果4.1 验证 TaoToken 通道是否通先用一个最简单的请求确认 Key 和地址没问题curl https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY返回模型列表 JSON 即表示通道正常。如果返回 401检查 Key 是否复制完整返回 404检查 base_url 是否写成了https://taotoken.net/api。4.2 验证执行计划对比是否有效在 Oracle 侧用DISPLAY_CURSOR对比两个子游标后你应该能明确回答三个问题快计划用了什么访问路径如INDEX RANGE SCAN慢计划用了什么访问路径如TABLE ACCESS FULL慢计划的Rows估算和实际差多少倍如果三个问题都能答上来说明定位到位。接下来做修复验证用 SQL Profile 或 Hint 固定快计划再跑一次业务 SQL观察V$SQL里是否还新增子游标。-- 用 SQLT 或 coe_xfr_sql_profile 固定计划后确认子游标不再增长 SELECT child_number, plan_hash_value, executions, buffer_gets FROM v$sql WHERE sql_id g07bjs22tcg72 ORDER BY child_number;预期结果修复后一段时间内child_number不再增加buffer_gets稳定在低位max_avg_sec回落到和min_avg_sec同一量级。4.3 验证 AI 解读结果是否可用把 AI 返回的“偏差最大步骤”和你在DISPLAY_CURSOR里看到的实际A-Rows对照。如果 AI 指出的步骤确实是你肉眼也怀疑的那一步说明解读有效。不要盲信 AI 给的 Hint它只是帮你缩小排查范围最终改 SQL 或加 Hint 前要在测试库验证。5. 本篇常见错排查报错一ORA-00942: table or view does not exist查V$SQL时出现。原因通常是当前用户没有查动态性能视图的权限。用SYS或授予SELECT_CATALOG_ROLE、SELECT ON V_$SQL后重试。报错二DISPLAY_CURSOR返回SQL_ID not found。子游标可能已经被刷出共享池。先查V$SQL确认SQL_ID还在如果不在改用DBMS_XPLAN.DISPLAY_AWR从 AWR 快照里找。报错三V$SQL_BIND_CAPTURE查不到值。绑定变量捕获默认只对部分语句生效且可能被刷出。确认_optimizer_capture_sql_plan_baselines或会话级10046已开并尽快查询。报错四TaoToken 请求返回 401 或 403。Key 失效、复制时带了空格、或者请求头没带Bearer。重新在控制台生成 Key确认Authorization: Bearer key格式正确。报错五AI 返回内容为空或截断。执行计划文本太长超出上下文窗口。把DBMS_XPLAN输出裁剪到关键步骤Id、Operation、Name、Rows、Cost去掉重复的分隔线再发。报错六固定计划后业务 SQL 仍偶尔变慢。检查是否有其他 SQL_ID 也命中了同一张表或者统计信息在夜间自动收集后计划又变了。把统计信息收集时间避开业务高峰并考虑锁定统计信息。6. 长期编码与 Agent 场景的接入建议如果你不只是临时排查而是要把“执行计划分析”做成日常流程——比如每天定时抓多计划 SQL、自动调 AI 生成报告、推送到群里——那用模型对话页面手动贴文本就不够了。这种长期编码/Agent 场景更适合走 Coding Plan把 TaoToken 作为统一通道接进你的脚本或内部工具。长期编码 / Agent 接入https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_campaignrewrite接入文档含 base_url、鉴权、模型列表https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_campaignrewriteAPI Keys 管理https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_campaignrewrite一个实用技巧把第 3.1 节的 SQL 存成脚本输出 CSV再用 Python 读 CSV 调 TaoToken API让模型只输出“疑似绑定变量窥探”的 SQL_ID 列表。这样每天跑一次比等告警再排查主动得多。执行计划对比和绑定变量捕获这两步建议在测试库先演练一遍确认DISPLAY_CURSOR和V$SQL_BIND_CAPTURE都能正常返回再上生产。