Monthly Archives: December 2010

倒底要不要使用Bind Variables

为了避免硬解析(即为了实现游标缓存),应该使用Bind Variables。这点大家都知道。 然而, Bind Variables如果出现在where子句中,它就会减弱查询优化器的某种能力:根据统计信息和SQL中的字面量选择最优的执行计划。  比如说,假定当前表里的age大都是50岁以下。如果SQL里指定了按 age<50 来查询,那优化器就会来一个全表扫描,快速返回相应数据; 如果SQL里使用的是 age < :age1,那优化器就不敢轻易走全表扫描了 (11g里部分地解决了这个问题,在此不表)。 那倒底要不要用Bind Variables呢? 《Troubleshooting Oracle Performance》给出的方案是:   1. 如果Bind Variable并没有出现where子句,那就没有理由不用它   2. 在小量数据查询环境下,如 OLTP中,硬解析的时间与执行时间相当甚至更大, 应该使用Bind Variable,避免硬解析   3. 在大量数据查询环境下,如 OLAP中,硬解析的时间与执行时间相比只是一个零头, 这时就应用直接用字面量,以免查询优化器选错了执行计划。

软解析、硬解析及其对性能的影响

SQL解析时要经历以下几个步骤:    1. VPD相关处理    2. 语法、语义、权限检查    3. 对SQL进行逻辑优化    4. 再进行物理优化 这其中会牵涉到游标的缓存读写: 看下缓存里有没有所需的游标,有就读出来直接用,没有就要创建一个出来用,用完后塞到缓存中。 如果缓存已存在,那就只需执行上面的步骤#1和步骤#2。 这就是软解析。 否则,就会执行所有步骤。这就是硬解析。 由于步骤#3和#4比较耗费CPU,而在缓存里创建新游标又比较耗内存,因此硬解析比软解析的开销要大很多,因此应该尽量避免硬解析。 要避免硬解析,就得尽量重用缓存中的游标。而游标是以SQL为Key的,要重用游标,就要尽量对同样的操作使用同样的SQL(大小写、空格都要一样),也就是说要用Bind Variables. ============================================================ 不过,软硬解析代价都其实都很高,因为它们都会产生对共享资源的竞争使用。 Oracle中,这些操作的并发性达到了“可串行化”级别,对性能的影响很大。