测试6——观察Optimizer_index_cost_adj 对执行计划的影响

简介:     在基于cbo的优化器模式下面,oracle会把sql语句的各种执行计划的成本做比较,取其最小的作为其最优执行计划,同时,在决定是用index scan 还是full table scan 访问一个表的时候,oracle会把index scan的执行成本转化为fts的成本,然后再根据其成本大小来决定执行计划,这个index scan 和full table scan 的比值即为 optimizer_index_cost_adj,这个初始化参数代表一个百分比,取值范围在1到10000之间.该参数表示索引扫描和全表扫描成本的比较。

    在基于cbo的优化器模式下面,oracle会把sql语句的各种执行计划的成本做比较,取其最小的作为其最优执行计划,同时,在决定是用index scan 还是full table scan 访问一个表的时候oracle会把index scan的执行成本转化为fts的成本,然后再根据其成本大小来决定执行计划,这个index scan full table scan 的比值即为 optimizer_index_cost_adj,这个初始化参数代表一个百分比,取值范围在1到10000之间.该参数表示索引扫描和全表扫描成本的比较。缺省值100表示索引扫描成本等价转换与全表扫描成本。

下面的例子具体说明了该参数的不同取值对执行计划的影响(下面的例子不能做为性能调整的根据,只是作为该参数的一个研究型文档,实际在调整该参数的时候,还是参考应用的类型(oltp/olap),及v$system_event 中的db file sequential readdb file scattered read的具体数值。

建立测试表

SQL> create table t as select * from dba_objects;
SQL> create index t_idx on t(owner);
SQL> SHOW PARAMETER OPTIMIZER_INDEX_COST_ADJ
NAME                                 TYPE        VALUE
------------------------------------ ----------- -----
optimizer_index_cost_adj             integer    100
SQL> SHOW PARAMETER DB_FILE
NAME                                 TYPE        VALUE
------------------------------------ ----------- -----
db_file_multiblock_read_count       integer     128
SQL> set autotrace traceonly explain;

SQL> select * from t where owner='HR';
Execution Plan
----------------------------------------------------------
Plan hash value: 1579008347
--------------------------------------------------------------------------------


| Id  | Operation   | Name  | Rows  | Bytes | Cost (%CPU)| Time    |
--------------------------------------------------------------------------------


|   0 | SELECT STATEMENT   |   |  2500 |505K|92   (0)| 00:00:02 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  2500 |505K|92   (0)| 00:00:02 |
|*  2 |   INDEX RANGE SCAN   | T_INX |  2500 |   | 8   (0)| 00:00:01 |

--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OWNER"='HR')

Note
-----
   - dynamic sampling used for this statement (level=2)

专门走一次全表扫描,看下cost是多少:

SQL>   select /*+ FULL(T) */ * FROM T WHERE owner='HR';


SQL>   select /*+ FULL(T) */ * FROM T WHERE owner='HR';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation | Name | Rows  | Bytes | Cost (%CPU)| Time|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  ||  2500 |   505K|  1591  (1)| 00:00:20 |
|*  1 |  TABLE ACCESS FULL| T|  2500 |   505K|  1591   (1)| 00:00:20 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("OWNER"='HR')
Note
-----
   - dynamic sampling used for this statement (level=2)

默认的optimizer_index_cost_adj =100全表扫描的成本是1591,索引范围扫描的成本92此时索引扫描的成本要比全表扫描的成本低,调整optimizer_index_cost_adj 参数,调整的基点: 全表扫描成本/索引扫描成本

SQL> SET AUTOTRACE OFF;

SQL> SELECT 1591/92*100 FROM DUAL;

1591/92*100
-----------
 1729.34783


接下来,是重点,我们取一个比这个基数略大的数值:1731

SQL> ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=1731;
Session altered.

SQL> SHOW PARAMETER OPTIMIZER_INDEX_COST_ADJ

NAME     TYPE VALUE
------------------------------------ ----------- ------------------------------
optimizer_index_cost_adj     integer1731


SQL> set autotrace traceonly explain;
SQL> select * from t where owner='HR';


Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id  | Operation  | Name | Rows  | Bytes | Cost (%CPU)| Time|
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  | |  2500 |   505K|  1591   (1)| 00:00:20 |
|*  1 |  TABLE ACCESS FULL| T |  2500 |   505K|  1591   (1)| 00:00:20 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("OWNER"='HR')

Note
-----
   - dynamic sampling used for this statement (level=2)

可以看到,此时奇怪的事情发生了,这个查询居然是走的全表扫描,而不是索引,这个参数到底是如何决定的呢?

原来: 在比较的时候,Oracle会把索引扫描的成本转换为全表扫描的成本,和全表扫描的COST进行比较.这个转换需要一个转换因子.就是optimizer_index_cost_adj:

optimizer_index_cost_adj * (Index Scan Cost) = 等价的 Full Scan Cost(比如刚才1731*92=159252 > 1591*100,所以选择了全表扫描,因为这个参数的权重让oracle决定走全表扫描的cost更低)

这个 等价的 Full Scan Cost 就是来和全表扫描成本进行比较的.

而这个转换因子的临界值实际上就是Full Scan Cost 和 Index Scan Cost的比值.

即:

optimizer_index_cost_adj = Full Scan Cost / Index Scan Cost(刚才1591/92 *100 =1731)


然后,我们把这个因子降低一点,看看是不是就会走索引呢?继续实验:

SQL> ALTER SESSION SET OPTIMIZER_INDEX_COST_ADJ=1725;
Session altered.


SQL> select * from t where owner='HR';
Execution Plan
----------------------------------------------------------
Plan hash value: 1579008347
-------------------------------------------------------------------------------------

| Id  | Operation    | Name  | Rows  | Bytes | Cost (%CPU)| Time|

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |   |  2500 | 505K|  1589   (1)| 00:00:20 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  2500 |505K|  1589   (1)| 00:00:20 |
|*  2 |   INDEX RANGE SCAN    | T_INX |  2500 |   | 138   (0)| 00:00:02 |


--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OWNER"='HR')
Note
-----
   - dynamic sampling used for this statement (level=2)

果然,此时又走的索引,但是cost变成了1589(我们知道full table scan的成本是1591),所以选择了成本较少的,那么这个值是怎么来的呢?

是实际的cost*optimizer_index_cost_adj 得到的(1589/1725=0.9211=92/100)


综上,我们明白了这个参数可以理解为一个权重的值,这个值越高,index scan的权重越小,越倾向于使用full table scan。一般OLTP系统里,建议设置较小的值10-50,这样就会有更多的查询走索引扫描,参考http://www.dba-oracle.com/oracle_tips_cost_adj.htm

For some OLTP systems, re-setting this parameter to a smaller value (between 10- to 30) may result in huge performance gains

相关文章
|
SQL 监控 测试技术
测试5——观察增量检查点
四:log file switch,会触发一个增量检查点,不过它会更新datafile header SQL> select cpdrt dirty,cpods on_disk_scn,cpodt on_disk_time,cphbt from x$kccc...
978 0
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
11月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1557 23
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
2069 24
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
1194 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
981 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
SQL 测试技术
除了postman还有什么接口测试工具
最好还是使用国内的接口测试软件,其实国内替换postman的软件有很多,这里我推荐使用yunedit-post这款接口测试工具来代替postman,因为它除了接口测试功能外,在动态参数的支持、后置处理执行sql语句等支持方面做得比较好。而且还有接口分享功能,可以生成接口文档给团队在线浏览。
663 2
|
存储 JSON API
Python测试淘宝店铺所有商品接口的详细指南
本文详细介绍如何使用Python测试淘宝店铺商品接口,涵盖环境搭建、API接入、签名生成、请求发送、数据解析与存储、异常处理等步骤。通过具体代码示例,帮助开发者轻松获取和分析淘宝店铺商品数据,适用于电商运营、市场分析等场景。遵守法规、注意调用频率限制及数据安全,确保应用的稳定性和合法性。
|
监控 API 开发工具
Socket.IO介绍,以及怎么连接测试Socket.IO接口?
Socket.IO 是一个用于浏览器和服务器间实时双向通信的库,支持低延迟消息传递、跨平台运行及自动重连。文章介绍了其特点与调试需求,并详细说明如何使用 Apifox 工具创建、连接、发送/接收 Socket.IO 事件,以及团队协作和调试技巧。掌握这些技能可提升实时应用开发效率与质量。
|
存储 测试技术 数据库
接口测试工具攻略:轻松掌握测试技巧
在互联网快速发展的今天,软件系统的复杂性不断增加,接口测试工具成为确保系统稳定性的关键。它如同“翻译官”,模拟请求、解析响应、验证结果、测试性能并支持自动化测试,确保不同系统间信息传递的准确性和完整性。通过Apifox等工具,设计和执行测试用例更加便捷高效。接口测试是保障系统稳定运行的第一道防线。