After a bit of a layoff to organise a few upcoming overseas trips, while watching plenty of Ashes Cricket and the brilliantly funny “Flight Of The Conchords” DVDs, it’s about time I got back to my humble little blog.
In Part II, we looked at a really bad way to set the optimizer_index_cost_adj parameter, by just setting it a really low value and allow indexes to blindly reign supreme in the database.
Remember, the purpose of the optimizer_index_cost_adj parameter is to accurately reflect differences and discrepancies in costs associated with single block I/Os when compared with corresponding multi-block I/Os so that the CBO considers and incorporates these discrepancies in its costings.
A second method of setting the optimizer_index_cost_adj parameter is to set it to a value that attempts to accurately reflect these comparative costs. So if a single block I/O is typically only half as expensive and/or only takes half the time to complete when compared to a multi-block I/O, then a reasonable setting for the optimizer_index_cost_adj parameter would be 50.
So how to set the optimizer_index_cost_adj parameter “intelligently” ?
Well, Oracle has excellent instrumentation and the comparative wait times for each of these types of I/Os are automatically measured and captured by Oracle. A single block I/O as performed typically by an index range scan is measured via the “db file sequential read” wait event while the multi-block I/O as typically performed during a FTS is measured via the “db file scattered read” wait event.
By determining the average wait times for each of these events and comparing the differences, one can determine how much longer it takes on average for one type of I/O to complete versus the other. This will then provide us with a reasonable starting point with which to set the optimizer_index_cost_adj parameter.
One can simply look at these average wait events for the database since startup by querying v$system_event:
SQL> select event, average_wait from v$system_event where event like ‘db file s%read’;
EVENT AVERAGE_WAIT ----------------------- ------------ db file sequential read .59 db file scattered read .78
In order to determine these wait events during a specific time period to perhaps better reflect typical loads during these times, one could also simply run a statspack or an AWR report and look at the wait event section of the report.
So in the above example, a “sequential” read only takes approximately 75% of the time when compared to a “scattered” read. As such, a value of 75 would be an appropriate starting value with which to set the optimizer_index_cost_adj parameter.
With the I/O costing model, the CBO is basing it’s costs on the number of I/Os performed by each possible access path. If an index is only going to take 75% of the time to perform it’s associated I/Os when compared to the time it takes to typical perform I/Os during a FTS, it’s reasonable to adjust the associated costs of an index access down to 75% of its overall costs.
This will hopefully have the desired effect of making it a “level playing field” between an index based access path and a FTS when determining how long all the I/Os associated with each possible execution path might take.
If we plug a value of 75 into the optimizer_index_cost_adj parameter and re-run the demo in Part Iwhere the CBO initially choose the more expensive FTS which had a cost of 65:
SQL> alter session set optimizer_index_cost_adj=75;
Session altered.
SQL> select * from bowie_stuff2 where id in (20, 30, 40, 50, 60);
10000 rows selected.
Execution Plan
———————————————————-
Plan hash value: 2964430066
——————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost |
——————————————————————————-
| 0 | SELECT STATEMENT | | 10000 | 175K| 60 |
| 1 | INLIST ITERATOR | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| BOWIE_STUFF2 | 10000 | 175K| 60 |
|* 3 | INDEX RANGE SCAN | BOWIE_STUFF2_I | 10000 | | 27 |
——————————————————————————-
We note the CBO is now choosing to use the index, which is the more appropriate plan as it provides a somewhat faster response that the previous FTS.
However, if we also re-run the demo from Part IIwith the optimizer_index_cost_adj also set to 75, where previously Oracle initially choose to use a FTS quite correctly:
SQL> alter session set optimizer_index_cost_adj=75;
Session altered.
SQL> select * from bowie where id between 1 and 1000;
1000873 rows selected.
Execution Plan
———————————————————-
Plan hash value: 1845943507
———————————————————–
| Id | Operation | Name | Rows | Bytes | Cost |
———————————————————–
| 0 | SELECT STATEMENT | | 1000K| 69M| 16499 |
|* 1 | TABLE ACCESS FULL| BOWIE | 1000K| 69M| 16499 |
———————————————————–
We note that the FTS is still selected as the change in the CBO index related costs were not significant enough to change the execution plan. A really low value of 2 for the optimizer_index_cost_adj parameter really stuffed things up previously, but a more appropriate value of 75 in this database has ensured that the FTS is still chosen when appropriate.
So in both scenarios, the CBO is now choosing an appropriate execution plan. By setting the optimizer_index_cost_adj parameter in a logical manner, consistent with the relative wait time differences between single and mutli-block I/Os, the CBO is more likely to choose appropriate execution plans.
Of course, there are always likely to be some discrepancies when dealing with such “averages”. We only have the one parameter after all which impacts the costs of all index range scan access paths, so we can only deal with averages. Perhaps there are some specific indexes which take significantly more (or less) time to complete than the average, as their associated I/Os are impacted by where the blocks might physically sit on the disk arrays, or on contention issues due to other concurrent activity, or on index caching characteristics (Note: I’ll discuss the optimizing_index_caching parameter at another time), etc. etc.
Same for some specific FTS which have multi-block I/Os that take significantly less (or more) time to complete than the average, as it’s associated I/Os might be also be impacted by similar factors. Perhaps some of these I/O characteristics and timings might change depending on the load on the system at different times of the day or week or month.
But that’s what an “average” value means right, some objects will have a higher (or slower) value while some have a lower (or faster) value.
So setting the optimizer_index_cost_adj parameter is not a precise science although of course the CBO in general is not a precise science either and close enough is usually good enough for the vast majority of cases. The name of the game is ensuring that the parameter is set to a value that’s in the “ballpark” and using the associated wait events to determine comparative wait times for single and multi-block I/Os is a reasonable way to do this.
However, despite being able to set the optimizer_index_cost_adj parameter in a reasonably “intelligent” manner, my preferred method of setting this parameter is still method number 3. That is to simply not set the optimizer_index_cost_adj parameter at all and leave it at the default value of 100 and use system statistics and the CBO CPU costing model instead.
By generating and maintaining accurate system statistics, you can effectively get the desired “level playing field” benefits of a well tuned optimizer_index_cost_adj parameter in a somewhat easier manner but with a few other added benefits as well. I would therefore strongly recommend the use and implementation of system statistics and leave the optimizer_index_cost_adj parameter well alone. IMHO, the optimizer_index_cost_adj parameter is there now only for backward compatibility reasons since the introduction of the CBO CPU costing model.
However, these discussions have not all been in vain because the optimizer_index_cost_adj parameter still has an impact even with system statistics in place. It’s just that the use of the optimizer_index_cost_adj parameter in conjunction with system statistics typically has the effect of screwing up the “level playing field” environment system statistics is meant to create.
Also, the costing formulas for indexes as previously discussed are still very much relevant as the CPU costing model often has little impact on the actual costs associated with using indexes. As I’ll discuss later, system statistics actually achieves a very similar outcome to the optimizer_index_cost_adj parameter. It’s just that it does so in a somewhat different manner by generally increasing the associated FTS costings to a more appropriate comparative value, rather than simply decreasing the index related costs, while taking both I/O and CPU overheads into consideration.
参考至:http://richardfoote.wordpress.com/2009/08/20/the-cbo-and-indexes-optimizer_index_cost_adj-part-iii/
如有错误,欢迎指正
邮箱:czmcj@163.com
相关推荐
- `OPTIMIZER_INDEX_COST_ADJ`:此参数在Oracle 8i中引入,旨在帮助CBO更好地评估索引访问路径与全表扫描之间的成本。但在版本9i及以上版本中,由于CBO算法已经足够智能,通常无需手动调整该参数。 - `OPTIMIZER_...
【CBO原书代码】是关于Oracle数据库优化器(Cost-Based Optimizer,简称CBO)的学习资源,由知名Oracle专家Jonathan Lewis编著。CBO是Oracle数据库系统中用于选择执行SQL查询最佳执行路径的关键组件。它通过计算不同...
影响优化器优化目标的因素主要有三个:OPTIMIZER_MODE 初始化参数、数据字典中的 CBO 统计数据、用来改变 CBO 优化目标的 Hints。 OPTIMIZER_MODE 初始化参数 ------------------------- OPTIMIZER_MODE 初始化...
Oracle 优化器有两种优化方式:基于规则的优化方式(Rule-Based Optimization,简称为 RBO)和基于代价的优化方式(Cost-Based Optimization,简称为 CBO)。 基于规则的优化方式(RBO)是指优化器在分析 SQL 语句...
CBO(Cost-Based Optimizer)和 RBO(Rule-Based Optimizer)是两种不同的优化器模式。CBO 根据成本估算选择执行计划,而 RBO 遵循简单的分级方法,使用 15 种级别要点,当接收到查询时,优化器将评估使用到的要点...
1. CBO:CBO尝试找到最低成本的访问数据的方法,以提高数据库的性能。它使用统计信息来确定执行计划。 2. RBO:RBO遵循简单的分级方法学,使用15种级别要点来评估查询时的成本。 三、资源消耗的SQL查询 如何定位...
- Oracle提供CBO(Cost-Based Optimizer)和RBO(Rule-Based Optimizer)两种优化器。 - 通过`OPTIMIZER_MODE`或`OPTIMIZER_GOAL`参数设置优化器模式,如`ALTER SESSION SET OPTIMIZER_GOAL=FIRST_ROWS`。 - 使用...
Oracle的Cost-Based Optimizer (CBO) 是一种自动选择最优执行计划的机制,它通过评估不同执行路径的成本来决定如何执行SQL查询。CBO会考虑各种因素,包括表的大小、索引的存在、数据分布等,以确定最有效率的查询...
* CBO(Cost-Based Optimization):基于成本的优化方式,Oracle 会根据表和索引的统计信息来计算运行 SQL 语句采用不同的执行计划所要耗费的成本。 * RULE(Rule-Based Optimization):基于规则的优化方式,Oracle...
3. 使用 Cost-Based Optimizer (CBO):设置optimizer_mode参数,CBO 需要统计信息,RBO 会选择不合适的索引 4. 定位资源消耗高的 SQL:根据 v$sqlarea 中的逻辑读/disk_read 和 CPU 使用率,查找当前 session 的当前...
通过合理配置OPTIMIZER_MODE参数、维护准确的CBO统计数据、灵活运用Hints,可以显著提升数据库系统的查询性能,满足不同应用场景的需求。在实践中,应根据应用特性选择最合适的优化目标,并结合统计信息的更新维护,...
在Oracle数据库管理中,CBO(Cost-Based Optimizer)是一种重要的查询优化策略,它根据操作的成本来决定最佳的执行计划。CBO通过分析表的统计信息,如行数、块数、索引信息等,来评估不同执行路径的代价,并选择最低...
- SQL优化改进,如CBO(Cost-Based Optimizer)的增强。 - Flashback Technology,支持快速回滚到数据库的某个历史状态。 3. **Unicode支持** OCI在11g版本中支持Unicode,这意味着开发者可以处理多种语言的数据...
CBO(Cost-Based Optimizer)是一种基于成本的优化器,RBO(Rule-Based Optimizer)是一种基于规则的优化器。CBO需要使用统计信息,据此计算最佳的执行计划,而RBO根据Oracle设定好的规则生成执行计划。由于不能窥视...
本文旨在深入探讨成本基础优化器(Cost-Based Optimizer,简称CBO)在Oracle数据库中的工作方式及其重要性。通过一个具体的示例,我们将逐步分析CBO如何根据表统计信息来选择最优查询执行计划。 #### CBO的基本概念...
Oracle提供了多种优化器模式,主要包括基于规则的优化器(Rule-Based Optimizer, RBO)和基于成本的优化器(Cost-Based Optimizer, CBO)。 - **RBO**:基于表和索引的定义信息来确定执行计划。它遵循一组预定义的规则...
4. CsB3O5(CBO)晶体:CBO是一种在紫外区域具有高透光性和高激光损伤阈值的非线性光学晶体。因其较大的有效非线性系数,CBO晶体成为产生紫外激光的优良选择。CBO可以用于倍频和三倍频转换,这里讨论的是利用CBO晶体...