sql in为什么有时候不走索引之oracle篇

数据库 ORACLE 11g

 

看例子:

表pm_project,有数据10万条,id 5000000-5100000

执行计划走一波explain plan for下面的SQL:

-- 走索引 唯一扫描 BY INDEX ROWID unique scan

select * from pm_project where pm_project_id

in (5000041, 5000042);

-- 走索引 区间扫描 BY INDEX ROWID range scan

select * from pm_project where pm_project_id

in (select pm_project_id from pm_project where pm_project_id < 5000025);

-- 全表扫描 full

select * from pm_project where pm_project_id

in (select pm_project_id from pm_project where pm_project_id > 5000025);

那是为什么呢?

第一条,写死的值,oracle通过优化器选择走唯一索引。

第二条,子查询有25条记录,oracle通过优化器选择了索引 range scan。

第三条,子查询有9万多条记录,oracle通过优化器选择了全表扫描,因为整个表才10万条,没必要走索引了。

 

那么问题来了,这个优化器怎么就这么做出选择了呢?

首先看下都有什么优化器?

优化器有RBO(Rule-based optimizer)和CBO(Cost-based optimizer)两种。

优化模式有Rule, Choose, First Rows, All Rows四种。

Oracle按照优化模式来选择Rule还是Cost:

Rule就是按照oracle的内部规则来优化,比如where语句里的列有索引就走索引,就算表很小,一次IO完事儿的事情,它也走索引,再回表,两次走完,就是这么耿直。

Cost就是表有个统计表,看看语句执行的开销cost,执行语句肯定要CPU和内存了,所以这个开销主要是指CPU和内存的开销,其他应该还有网络,集群等因素的影响。这些统计数据就是来自表和索引的统计信息。

所以,

设置优化模式为 Rule - 走RBO。

设置优化模式为Choose,First Rows, All Rows - 并且有统计信息,走CBO,没有就走RBO。

First和All的区别就是用CBO时,First先返回几行,减少响应时间,All返回所有的,减少总体的吞吐量,就是来回请求的开销嘛。

 

那统计信息是什么呢?

就是优化器用来选择执行计划时,所使用的数据,详情请看官方:https://docs.oracle.com/cd/B19306_01/server.102/b14211/stats.htm#i41591

 

那么怎么查看我的数据库用的是设么优化模式呢?

select value FROM V$PARAMETER WHERE name='optimizer_mode';

用的是 ALL_ROWS

 

那么我的表和索引的统计信息怎么查看呢?

select * from user_tables where table_name = 'PM_PROJECT' and num_rows is not null;

select * from user_indexes where table_name = 'PM_PROJECT' and num_rows is not null;

都有数据的,CBO没跑了。

 

所以走的是CBO + ALL_ROWS。

具体如何计算的,以后再研究吧,先立个flag在这儿。

 

 

 

你可能感兴趣的:(数据库)