ash中可通过查询latch等待激增且sql_id高频重复、plan_hash_value不稳定、time_waited异常高的会话,结合执行计划中驱动表选择错误和cardinality严重偏差来定位笛卡尔积问题。
ash 中怎么看笛卡尔积引发的 latch 等待?
笛卡尔积本身不会报错,但会在执行时产生海量中间行,导致 latch: cache buffers chain 或 latch: row cache objects 等等待激增。ash(active session history)是定位这类问题最直接的入口。
关键不是查“笛卡尔积”这个词,而是找「高并发、低效率、长等待」的组合信号:
-
session_state = 'WAITING'且event频繁出现latch: cache buffers chain -
sql_id对应的program是 SQL*Plus 或应用连接池线程,但time_waited异常高(秒级) - 同一
sql_id在 ASH 中大量重复出现,且sample_time密集集中在某几分钟内 - 关联字段缺失或无效时,
plan_hash_value往往不稳定(多次执行 plan hash 不同),说明优化器反复尝试不同连接顺序
用哪些 ASH 查询语句快速抓可疑 SQL?
别翻全量 ASH 视图,先用带过滤的聚合查法缩小范围。以下语句可直接在 SQL*Plus 或 OEM 中运行:
SELECT sql_id, event, COUNT(*) cnt, ROUND(AVG(time_waited)/1000,2) avg_sec FROM v$active_session_history WHERE sample_time > SYSDATE - 1/24 -- 查最近1小时 AND event LIKE 'latch:%' AND sql_id IS NOT NULL GROUP BY sql_id, event HAVING COUNT(*) > 50 ORDER BY cnt DESC;
拿到高嫌疑 sql_id 后,立刻查执行计划:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_ASH('&sql_id', NULL, 'ALL'));
重点看:JOIN ORDER 是否把大表当驱动表、Cardinality 预估是否离谱(比如预估 1 行,实际扫描百万行)、是否有 NESTED LOOPS 但没走索引(意味着可能在做全表扫+全表扫的嵌套)
为什么 RBO(Rule-Based Optimizer)下笛卡尔积更隐蔽?
Oracle 旧系统仍可能启用 /*+ RULE */ 提示或设置 optimizer_mode = RULE,此时优化器不依赖统计信息,而按固定规则选驱动表:从 FROM 子句**最右表开始**作为驱动表。
这意味着如果写法是 FROM t1, t2, t3 WHERE t1.id = t2.id(漏了 t2.id = t3.id),RBO 会先取 t3,再与 t2 做连接,最后才连 t1 —— 而 t2 和 t3 之间无关联条件,直接触发笛卡尔积。
这种问题在 ASH 中表现为:sql_id 的 module 显示为 SQL*Plus 或 JDBC Thin Client,但 blocking_session 为空,且 wait_class 长期卡在 Concurrency;执行计划里看不到 HASH JOIN 或 MERGE JOIN,全是 NESTED LOOPS 且无索引访问路径。
EXISTS 替代 JOIN 时,ASH 中的等待模式会变吗?
会变,而且变化明显:原本密集的 latch: cache buffers chain 等待大幅减少,DB CPU 占比上升,session_state 更多处于 ON CPU 状态。
这是因为 EXISTS 子查询通常能利用半连接(semi-join)优化,配合索引快速定位后即短路退出,避免生成中间结果集。ASH 中体现为:
- 同一业务逻辑改写后,
sql_id改变,新sql_id的time_waited总和下降 80% 以上 - 原 SQL 的
elapsed_time在 ASH 中常达数分钟,新 SQL 多数样本time_waited为 0,in_parse或in_hard_parse比例升高(首次硬解析开销) - 若新 SQL 仍慢,要检查 EXISTS 里的子查询是否走了索引 —— 看 ASH 的
p1text/p1是否含file#/block#,有则说明在物理读,需补索引
真正难排查的不是语法错误,而是那些“看起来有连接条件、其实漏写了中间关联”的三表及以上查询 —— 它们在 ASH 里不显眼,却在高峰期突然拖垮整个实例。盯住 latch 等待 + plan_hash_value 波动 + cardinality 预估偏差,比看执行计划本身更早发现问题。











