optimizer_mode
optimizer_mode这个参数至关重要,因为通过它可以向查询优化器指明“高效率”这个词的含义。通常来讲,它的意思可能是“更快一些”“使用更少的资源”或者其他的意思。因为在使用数据库处理数据时,通常希望处理速度越快越好。
因此,高效的含义应该是“用最快的方式执行SQL语句而不浪费不必要的资源”。这对于总是完全执行的SQL语句没有问题(例如,INSERT语句)。而另一方面,对于查询,则会有细微的差异。比如说,应用程序并不是必须要获取查询返回的所有行。换句话说,查询可能是部分执行的。
优化处理流程以尽可能快速地返回初始数据的例子,因为最前面的几页几乎总是用户唯一真正会去访问的页面。
希望整个页面都可以访问并且正确排版,也就是说我会开始阅读。在这种情况下,处理流程应该被优化为尽快提供所有数据而非一小部分。
每一个应用程序(或程序的一部分)都会归结为以下两种策略:
Ø 要么是优先快速传递结果集中最靠前的数据,
Ø 要么是优先快速传递整个结果集(这其实等同于快速传递结果集的最后一行)。
要为optimizer_mode初始化参数选择合适的值,应该首先问自己一个问题:是让查询优化器产生快速返回首行数据的执行计划更重要,还是快速返回末行数据的执行计划更重要。
Ø 如果快速返回末行数据更重要,应该使用值all_rows。这是最常用的配置。
Ø 如果快速返回首行数据更重要,应该使用值first_rows_n(n的取值为1、10、100或1000)。这个配置应该只在应用程序部分获取的结果集大于该参数指定的行数时才被使用。对于已经存在的应用程序,可以通过比较执行和v$sqlarea视图中的end_of_fetch_count列来检查这一点。注意更早期的首行优化器实现(也就是,通过值first_rows进行配置)不应该再被使用了。事实上,提供这个值仅是为了向后兼容。
默认值是all_rows。还要注意INSERT、DELETE、MERGE和UPDATE语句总是使用all_rows来优化。这样做是很有道理的,因为这些SQL语句必须在将控制权交还给调用者之前处理所有的数据。
警告 首行最优化的关键思想是避免阻塞操作(也就是说,直到运行完毕之前不会产生任何数据的操作)。为此,通常更倾向于嵌套循环连接而非散列连接(直到散列表建立起来之前都是阻塞状态)或合并连接(直到两个输入都完成排序之前都是阻塞状态)。此外,在某些情形中,ORDER BY操作(直到数据被完成排序之前都是阻塞状态)会由索引范围扫描取代。对于大的结果集,首行优化未必能够带来最优的性能表现。所以,最重要的是,只有在调用的应用程序只抓取大结果集的一部分时才使用首行优化。
optimizer_mode初始化参数是动态的,并且可以在实例和会话级别修改。在12.1多租户环境下,也可以在PDB级别设置它。此外,通过下面其中一种hint,也可以在语句级别设置它:
Ø all_rows;
Ø first_rows(n),n是大于0的任何自然数。
optimizer_features_enable
在每个数据库版本中,Oracle都会在查询优化器中引入或启用新的特性。如果正在升级到一个新的数据库版本并希望保留查询优化器旧的行为,可以通过将optimizer_features_enable初始化参数设置为升级之前的数据库版本来实现。遗憾的是,并不是所有的新特性都可以通过这个初始化参数来禁用。
举例来说,如果你在11.2版本中将其设置为10.2.0.4,就不会获得与10.2.0.4版本完全一样的查询优化器。出于这个原因,我通常建议使用默认值,也就是与数据库可执行文件使用相同的版本号。另外,Oracle Support文档 Use Caution if Changing the OPTIMIZER_FEATURES_ENABLE parameter
After an Upgrade(1362332.1) 也提供了类似建议。
提示 改变optimizer_features_enable 初始化参数的默认值只是短期解决方案。迟早应用程序都应该适应(尽量充分利用)新的数据库版本。
optimizer_features_enable初始化参数合法的值是类似10.2.0.5、11.1.0.7或11.2.0.3这样的数据库版本号。因为并不会针对这个参数的补丁级别更新文档(特别是Oracle Database Reference手册),所以可以通过以下SQL语句来生成支持的值:
select value from v$parameter_valid_values
where name='optimizer_features_enable';
optimizer_features_enable初始化参数是动态的,并且可以在实例和会话级别修改。在12.1多租户环境下,也可以在PDB级别设置它。此外,也可以在语句级别通过optimizer_features_enable这个hint来设置一个值。下面的两个例子分别通过这个hint设置默认值和一个具体值:
Ø optimizer_features_enable(default)
Ø optimizer_features_enable('10.2.0.5')