【IT168 技术文档】
任何SQL语句优化引擎的核心是判定获得SQL语句目标数据的最廉价和最有效的访问路径的能力,使用绑定变量可以限制需要存储在库缓存中返回相似结果集的SQL语句游标的数量。本文介绍Oracle 11g中的新特性 – 自适应游标共享 – 并说明实际情况中该如何使用它,以及如何限制带有绑定变量的SQL语句的硬解析,同时提高这些语句的执行效率。
正如我过去做老师时告诉学生的那样,我有一个好方法可以避免数据库性能降低,说来也很简单,就是要求应用程序开发人员不要在数据库运行任何SQL语句,但这的确引来不少人的笑声和嘲笑,还是回到现实中来吧,讨论一下建立有效SQL语句的途径,我认为没有什么标准可供借鉴,但构造不佳的SQL语句迟早会导致联机事务处理(OLTP)系统、决策支持系统(DSS)或混合数据库表现不佳。
“偷窥”绑定变量:这不是作弊
幸运的是,Oracle数据库为我们提供了一些很好的工具,用以确定需要改善性能的SQL语句,并为提升它们的性能提供建议,这个方法的核心是当确实需要一个新的执行计划时,我们可以修改基于成本的SQL优化器解析SQL语句的方式。当然,当一条语句第一次执行时必须硬解析,这样优化器可以确定获取所需数据的非常好的路径,因为解析是一个相对费时的操作,因此,DBA通常会限制存储在库缓存中的唯一性游标的数量,特别是在联机事务处理环境下,相同的语句可能会被执行成百上千次,它们为用户会话返回相似的结果集。
设置有效的游标共享最简单的方法就是按照应用程序工作量的需要为CURSOR_SHARING初始化参数设定合适的值,将这个参数的值设为SIMILAR告诉优化器当SQL语句完全相同,除了谓词部分外,可以使用游标共享,执行计划提供相等或更优的性能,同样,将其值设为CURSOR_SHARING时,不论是否存在更好的执行计划,告诉优化器强制共享游标,当SQL语句包含绑定变量时,有极好的机会提供这方面的性能优势,但当优化器在不知道是什么值来填充产生的游标时,怎样才能构建一个有效的执行计划呢?
早在Oracle 9i就进行了一些尝试,为了克服可能出现的非非常好的的执行计划,引入了绑定变量偷窥,顾名思义,当一个包含绑定变量的SQL语句首次执行时,Oracle会快速查看这些绑定变量的一个真实值,以便构建一个非常好的的执行计划,这个方法的优点很明显:不再是猜测非常好的的执行计划了,因为那样产生的执行计划可能并不是非常好的的,基于成本的优化器使用真实的值来构建执行计划。
但不幸的是,这个方法对于非OLTP系统的缺点也很明显,例如,如果决策支持系统下次运行的查询指定了一套绑定变量的值,那此时要想高效地执行查询,需要一个完全不同的执行计划吗?实际上,这种数据仓库环境并不罕见,对于决策支持系统,它可能非常希望有多个可用的执行计划作为候选,因为一个绑定变量集可能返回的结果集只包含几百行的数据,而另一套绑定变量可能返回几百万行数据,因此,Oracle建议保留CURSOR_SHARING作为该初始化参数的默认值,以强制产生一个新的更有效的执行计划。