暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle性能优化:SQL优化思路之十二——索引有序化max/min

oracleEDU 2017-11-07
1583

max() 和 min() 应该是大家常用的使用频率很高的sql写法,这种聚合查询max(),min()与索引的关系是怎样呢,能用索引吗?当然可以(但是索引列必须要建主键或者要写where column is not null)。用上了什么样的索引扫描方式呢?前面介绍了INDEX FULL SCAN扫描方式,这里介绍max()和min()利用的另一种索引扫描类型INDEX FULL SCAN (MIN/MAX)。

索引结构

索引结构是从root到branch最后到leaf,好象一个金字塔。最下面的叶子层(也就是金字塔的底部)其实是有序的,比如从左到右值是从小到大,或者从大到小。这样一来大家认为取max()或者 min()还需要INDEX FULL SCAN吗,找到头或尾不就找到最大或最小值,还需要遍历leaf吗?不需要了。index full scan(max/min)蕴含着stopkey的机制,从最左边或者最右边的叶子节点开始扫描,读到第一个值后就停止扫描。

案例环境

SQL> drop table t purge;

SQL> create table t as select * from dba_objects;

SQL> update t set object_id = rownum;

SQL> alter table t add constraint pk_object_id primary key (OBJECT_ID);

SQL> set autotrace on

SQL> set linesize 1000

测试案例

SQL> select max(object_id) from t;

使用INDEX FULL SCAN (MIN/MAX)扫描类型

同样min()也是,执行计划这里就不再列出。

SQL> select min(object_id) from t;

没用到索引的情况

(看代价和逻辑读的差异)

SQL> select *+full(t)*/ max(object_id) from t;

有索引的情况下,记录数增加,看性能变化

SQL> set autotrace off

SQL> create table t_max as select * from dba_objects;

SQL> insert into t_max select * from t_max;

SQL>

SQL>

SQL> select count(*) from t_max;

  COUNT(*)

----------

    551688

SQL> create index idx_t_max_obj on t_max(object_id);

记录增加对性能也不会有影响。

object _id如果允许为空,加个索引后,还会走INDEX FULL SCAN (MIN/MAX)高效算法吗?答案:会,取最大值最小值忽略空值。

附加

max()和min()同时出现时,Oracle使用的扫描方式还是这样吗?

测试案例:

SQL> select max(object_id),min(object_id) from t;

执行计划

并没有使用INDEX FULL SCAN (MIN/MAX)索引。

原来INDEX FULL SCAN (MIN/MAX)是无法一次取到两个值的,所以ORACLE不得不选择了INDEX FULL SCAN ,把叶子的索引扫了个遍,同时取到了两个值。

怎样使用高效的INDEX FULL SCAN (MIN/MAX)索引呢?

将语句改写成如下:

SQL> select(select max(object_id) from t) a,(select min(object_id) from t)b from dual;

执行计划


总结:

max() 和 min() 是大家常用的使用频率很高的sql写法,各种报表中需要这样编写的地方很多,对这样的查询建立索引,在保证该列不空的情况下,就有可能利用到INDEX FULL SCAN (MIN/MAX)这个索引扫描方式,能为查询性能带来很大的提高。



最后修改时间:2021-04-28 20:26:12
文章转载自oracleEDU,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论