何时走索引

crazywolf 2014-07-07 05:01:12
问一个老生常谈的问题,oracle何时走索引,今天遇到一个奇怪的问题,查询一个表最近七天内的数据,数据量2w条左右,全表的数据量达到50多w,根据分析的很,数据量远远没有达到1/3,如果建了索引,应该会走索引才对,可这就奇怪了,它偏偏不走索引,但是加了order by之后,它就能走索引了,更奇怪的事是加了order by再加一个没有索引的条件,它又不会走索引了,感觉直接上sql说得清楚些,如下:
全部的数据量:
符合条件的数据量:
查询最近七天的数据不会自动走索引(create_time上建了索引)(执行计划):

加了orderby之后能走索引:
再加一个没有索引的条件,又变成了不会走索引:

我知道可以使用hint让它强制走索引,但是我想了解一下oracle优化器是怎么思考,有木有大虾能解释一下不,小弟不胜感激

...全文
204 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
小灰狼W 2014-07-09
  • 打赏
  • 举报
回复
如果create_time可为空,由于索引中不会存储空值,当某一条记录的create_time为空时,索引中不会有对应的项,如果走索引可能会造成结果不准确。也就是说,count(create_time)可能不等于count(*)
小灰狼W 2014-07-09
  • 打赏
  • 举报
回复
你的第一个语句要让它走索引,有两种方式 1: select count(create_time) from ... where create_time>.... 2: 给create_time字段加上非空约束 这样的话,系统就可以在create_time的索引中完成count操作而不用到表中去扫描,即使选择性不高,也可以降低逻辑读。也就是说,此时走索引的成本低于全表扫描的成本
crazywolf 2014-07-08
  • 打赏
  • 举报
回复
引用 4 楼 wildwave 的回复:
查询一半也会走索引,说明你的查询中只涉及到了gendate字段
但是同样的查询只涉及create_time为啥就不会走索引呢?
小灰狼W 2014-07-08
  • 打赏
  • 举报
回复
查询一半也会走索引,说明你的查询中只涉及到了gendate字段
crazywolf 2014-07-08
  • 打赏
  • 举报
回复
引用 2 楼 wildwave 的回复:
何时走索引,不是几句话能说清楚的 这里的1/3不准确,具体的值不好说,由cbo来判断。大概的量级在1/10左右吧 cbo的思考方式是找出成本最小的那个执行计划,即执行语句所有时间的最短估计。 在Oracle 9.2的costing model中,成本的计算公式为 Cost = ( #SRds * sreadtim + #MRds * mreadtim + #CPUCycles / cpuspeed ) / sreadtim where #SRDs - number of single block reads #MRDs - number of multi block reads #CPUCycles - number of CPU Cycles sreadtim - single block read time mreadtim - multi block read time cpuspeed - CPU cycles per second 后续版本做了一些调整,但是差距不大 在你的例子中,优化器大概认为走全表扫描效率会更高一点,但是相差不大,因此当你加上排序时,若走全表扫描,比起走索引的执行计划要多出排序的这部分成本。 将谓词条件的选择性提高,例如create_time >trunc(sysdate-2) 走索引的可能性将会更高 若非肯定,谨慎使用Hint,它可能会造成严重的性能问题 另外,优化器的很多数据来源于统计信息。如果表的统计信息不正确可能会误导优化器 可以使用dbms_stats包中的存储过程来调整统计信息
hint肯定是肯定了才使用,对表进行了分析,但是结果还是一样,更奇怪的是我再另一个表中,数据量达到800w左右的一个表,同样的使用一个date类型作为索引,也是使用gendate>sysdate-300查出来的数据将近100w也是会走索引,甚至查询出一半的数据也会使用index fast full scan,两边的表都是进行过分析的,难道这个和oracle数据库的参数设置有关系么?实在令人费解啊!
小灰狼W 2014-07-07
  • 打赏
  • 举报
回复
何时走索引,不是几句话能说清楚的 这里的1/3不准确,具体的值不好说,由cbo来判断。大概的量级在1/10左右吧 cbo的思考方式是找出成本最小的那个执行计划,即执行语句所有时间的最短估计。 在Oracle 9.2的costing model中,成本的计算公式为 Cost = ( #SRds * sreadtim + #MRds * mreadtim + #CPUCycles / cpuspeed ) / sreadtim where #SRDs - number of single block reads #MRDs - number of multi block reads #CPUCycles - number of CPU Cycles sreadtim - single block read time mreadtim - multi block read time cpuspeed - CPU cycles per second 后续版本做了一些调整,但是差距不大 在你的例子中,优化器大概认为走全表扫描效率会更高一点,但是相差不大,因此当你加上排序时,若走全表扫描,比起走索引的执行计划要多出排序的这部分成本。 将谓词条件的选择性提高,例如create_time >trunc(sysdate-2) 走索引的可能性将会更高 若非肯定,谨慎使用Hint,它可能会造成严重的性能问题 另外,优化器的很多数据来源于统计信息。如果表的统计信息不正确可能会误导优化器 可以使用dbms_stats包中的存储过程来调整统计信息
  • 打赏
  • 举报
回复
优化器CBO太难了,同等大神

17,082

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧