首页 > 数据库 >警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描

时间:2022-10-21 12:32:16浏览次数:72  
标签:STATUS INDEX tree 扫描 索引 MILESTONE Oracle

生产环境慢查询统计中,发现表 STATUS 的 MILESTONE 字段条件查询时进行了全表扫描。表 STATUS 的 MILESTONE 字段定义如下:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_字段


针对上述问题创建索引:

create index STATUS_MILESTONE on STATUS("MILESTONE") tablespace DFS_INDEX2;

分析执行计划发现问题语句依然走的是全表扫描,新建的索引 STATUS_MILESTONE 没有用到。第一反应是索引是不是没有创建成功?

查看索引库发现该索引确实存在并且生效:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_oracle_02


查看 STATUS 表 DDL 也可以看到该索引的定义:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_oracle_03


看来我们的索引被 Oracle 忽视了。Oracle 无视现有索引有很多种原因,但一般来讲有这两种原因:

  • 该 sql 的写法导致 Oracle 无法使用已有索引(最左前缀原则,请参考博客《B-Tree 索引和 Hash 索引的对比》)。
  • Oracle 基于成本的优化器选择不使用该索引。

测试库中 STATUS 表记录数:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_oracle_04


观察 STATUS 表 MILESTONE 字段相关数据特点,发现该字段的记录只有少数不同值的列:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_字段_05


现在我们以简单查询语句 select * from status S WHERE S.MILESTONE = ‘IFFDEL’ 来验证执行计划:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_oracle_06


全表扫,cost 为 25。

强制优化器走索引 STATUS_MILESTONE 并分析其执行计划:

警惕 Oracle 索引优化时陷阱之无效的索引范围扫描(INDEX RANGE SCAN)导致的全表扫描_执行计划_07


索引范围扫描,cost 61,比全表扫还昂贵。很明显本文描述问题命中上述不走索引的两大主流原因之“Oracle 基于成本的优化器选择不使用该索引”的情况。

如果创建索引时不进行显式说明,Oracle 默认创建的都是 B-tree 索引。也就是说上文中我们创建的索引 STATUS_MILESTONE 是一个 B-tree 索引。

B-tree 的优势在于大量不同的记录,而位图索引的优势在于相对于表中行总数而言只有少数不同值的列,所以本文 select * from status S WHERE S.MILESTONE = ‘IFFDEL’ 示例用位图索引效果会更好。重新创建索引如下:

drop index STATUS_MILESTONE;
create bitmap index STATUS_MILESTONE_BITMAP on STATUS("MILESTONE") tablespace DFS_INDEX2;

当然,在多字段检索复杂查询中,可能还是联合 B-tree 索引优势更明显。
总结:
造成无效的范围索引扫描有很多原因,除了本文中的少数不同值的情况之外,还可能存在以下可能:

  • 使用了范围谓词,如 <、>、LIKE 和 BETWEEN。
  • 只使用到了组合索引的部分列。

参考资料



标签:STATUS,INDEX,tree,扫描,索引,MILESTONE,Oracle
From: https://blog.51cto.com/defonds/5782138

相关文章

  • Mysql索引(究极无敌细节版)
    参考了:https://www.jianshu.com/p/ace3cd6526c4推荐up主https://space.bilibili.com/377905911推荐书籍《mysql是怎样运行的》推荐极客时间《MySQL实战45讲》——林晓......
  • Typescript索引和接口继承
    索引签名我们既可以使用数字索引去访问数组元素,也可以使用字符串索引去访问数组对象上的属性和方法。constcourse=['math','English','Chinese']//访问数组中的第二个......
  • MASA MAUI Plugin (四)条形码、二维码扫描功能
    背景MAUI的出现,赋予了广大.Net开发者开发多平台应用的能力,MAUI是Xamarin.Forms演变而来,但是相比Xamarin性能更好,可扩展性更强,结构更简单。但是MAUI对于平台相关的实现并......
  • mysql数据索引,加快查询速度
    一、什么是索引?在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。通过索引,查询数据时不用读完记录的所......
  • mysql技术总结1-索引结构
    最近把mysql的知识重新梳理了下。分几个点。mysql索引结构mysql查询优化mysql事务mysql架构设计mysql高可用这篇写一些索引结构。先搞几个问题1、mysql的存储引擎......
  • uva688 (扫描线)
    AmobilephonecompanyACMICPC(AdvancedCellular,Mobile,andInternet-ConnectedPhoneCorporation)isplanningtosetupacollectionofantennasformobileph......
  • h5页面在ios上无法滑动与z-index无效的情况
    ps:俩问题产生的原因是引用了scroll.js文件问题一:无法滑动scroll.js文件禁用了滑动事件,在不需要scroll方法的时候,解除禁用即可。/***滑动限制***/stop(){......
  • mysql联合索引和复合主键
    最近优化一个页面,数据5GB(可能要算上索引),单个查询要300s左右,数据表建有联合索引,顺便复习总结下联合索引的东西,本文内容皆来自网络,如有侵权,请联系我删除。联合索引单一索......
  • Elasticsearch 如何实现类主流搜索引擎广告置顶显示效果?
    1、需求私信问题:Elasticsearch如何实现类似百度广告置顶显示给定商品数据的效果?置顶显示某特定数据就是:搜索某关键词,出现关联广告置顶显示的效果。举例:百度搜索“电动汽车......
  • 干货 | Elasitcsearch7.X集群、索引备份与恢复实战
    Elasticsearch最少必要知识实战教程直播回放1、问题引出ES中文社区中,有如下问题:问题1:存储数据,data目录从一个机器直接移到一台新的机器是否可以直接使用?问题2:es升级时,data......