sql 绑定变量可以减少硬解析的次数,极在提高oracle内存的使用率,这一点大家应该是很清楚了。但是是否绑定变量并一定是永远安全可靠的,它对CBO产生高效正确的执行计划有时是会有影响的。假如一个表的数据有非常在的倾斜,比如一个只有一个ID字段的表T,T表上有10W条记录,其中ID=1的记录只有1条,ID=2的记录有99999条。
如果有这么一条查询语句:select * from t where id=:x,x是一个变量。
采用绑定变量,那么在sql语句第一次执行时,就会硬解析阶段进行bing peeking,第二次执行就不会再有硬解析,所以也就不会进行bing peeking了。如果第一次查询时,变量x=1, 那么bing peeking后, CBO产生的执行计划是将会采用全表扫描, 当进行第二次查询时,变量x=2, 由于是第二次执行,所以不进行bing peeking,也就不会重新评估执行计划,那么,还是采用全表扫描,这样的执行计划就是错误的了,应该用索引。
所以,绑定变量后,后面的查询都会一直使用第一次的查询时产生的执行计划,但是谓词不同 可能需要不同的执行计划才能有高效的查询效率,这一点绑定变量无法顾及到,这也是绑定变量的一个缺点吧。可以通过清空共享池来使下次执行SQL进行硬解析。
清空共享池操作语句:alter system flush shared_pool;