绑定变量是降低CPU消耗的关键,通过复用执行计划避免重复硬解析;动态SQL必须显式使用USING子句传参,否则退化为硬解析;绑定变量窥探可能导致执行计划劣化,需结合统计信息或特殊处理应对。

硬解析才是CPU消耗的真正源头
Oracle每次执行一条全新结构的SQL,都必须走完整硬解析流程:语法检查、语义验证、权限校验、数据字典访问、执行计划生成。这个过程极度依赖CPU,且需争抢共享池中的library cache latch。动态SQL若用字符串拼接(如 'SELECT * FROM emp WHERE dept_id = ' || v_dept),每换一个值就产生一条新SQL文本,触发一次硬解析——1000次查询=1000次硬解析。
绑定变量让Oracle复用同一游标
使用 EXECUTE IMMEDIATE ... USING 后,SQL文本固定为 'SELECT * FROM emp WHERE dept_id = :d',Oracle对其计算出唯一hash值,首次执行做硬解析并缓存执行计划;后续所有调用都命中同一游标,仅做软解析(验证权限+绑定类型),开销下降90%以上。
- 软解析不重查数据字典,不重新生成执行计划
- 无需竞争library cache latch,高并发下无闩锁争用
- 共享池内存占用稳定,避免因大量相似SQL挤占空间导致其他SQL被老化淘汰
PL/SQL静态SQL天然绑定,但EXECUTE IMMEDIATE必须显式写
PL/SQL块内直接写的 SELECT ... WHERE id = v_id 会被Oracle自动识别为绑定变量,无需额外操作;但 EXECUTE IMMEDIATE 是运行时拼接,必须显式用 USING 子句传参,漏掉或写成字符串拼接就退化为硬解析。
- ✅ 正确:
EXECUTE IMMEDIATE 'SELECT name FROM emp WHERE dept_id = :d' INTO l_name USING v_dept; - ❌ 错误:
EXECUTE IMMEDIATE 'SELECT name FROM emp WHERE dept_id = ' || v_dept; - ⚠️ 注意:
USING中变量类型要与列匹配,否则隐式转换可能使索引失效(如NUMBER列传入字符串)
容易被忽略的边界问题:绑定变量窥探与数据倾斜
Oracle在首次硬解析时会“窥探”绑定变量的实际值来生成执行计划,这在数据分布均匀时很有效;但若首次传入的是异常值(比如某部门占全表95%记录),生成的全表扫描计划会被后续所有值复用,导致本该走索引的查询变慢。这不是绑定变量本身的问题,而是优化器基于单次采样做决策的固有限制。
这种场景下不能简单弃用绑定变量,而应结合直方图统计信息、OPTIMIZER_FEATURES_ENABLE 调整,或对极端值分支单独写SQL——绑定变量是默认正确选择,例外需要主动识别和干预。











