暂无图片
暂无图片
暂无图片
暂无图片
暂无图片
为何在查询中索引未被使用 (文档 ID 1549181.1).pdf
25
9页
2次
2025-03-06
100墨值下载
版权所有 (c) 2025Oracle。保留所有权利。Oracle 机密。
* 为何在查询中索引未被使用 (文档 ID 1549181.1)
文档内容
用途
排错步骤
快速检查
表上是否存在索引?
索引是否应该被使用?
索引本身的问题
索引列或者索引的前置列是否在单表(non-join)查询的 Where 条件中(predicate list)?
索引列是否用在连接谓词中(join predicates)?
索引列在 IN 或者多个 OR 语句中?
索引列是否被函数修改?
隐式类型转换(implicit type conversion)是什么?
是否在语义(semantically)上无法使用索引?
错误类型的索引扫描?
是否索引列为可空?
NLS_SORT是否设置为二进制(BINARY)?
是否使用的是不可见索引(invisible indexes)?
优化器和成本计算相关问题
是否存在准确且合适的统计信息(Statistics)?
一个索引是否与其它的索引有相同的等级或者成本(cost)?
索引的选择度不高?
在总体成本中,表扫描的成本占大部分
访问空索引并不意味着比访问有值的索引高效。
参数设置
其它问题
是否使用了视图/子查询?
是否存在远程表(remote table)
是否使用并行执行(PX?
是否是包含了子查询的Update语句?
查询是否使用了绑定变量?
查询是否引用了带有延迟约束的列?
索引提示(hint)不工作
有用的 hints:
参考
适用于:
文档 1549181.1 https://support.oracle.com/epmos/faces/DocumentDisplay?_a...
1 9 2025/3/6 16:05
Oracle Database Cloud Exadata Service -
版本 N/A 和更高版本
Oracle Database Backup Service -
版本 N/A 和更高版本
Oracle Database Cloud Service -
版本 N/A 和更高版本
Oracle Database - Standard Edition -
版本 8.1.7.4 和更高版本
Oracle Database - Personal Edition -
版本 8.1.7.4 和更高版本
本文档所含信息适用于所有平台
用途
这篇文章用来解答下面的问题:为什么我的索引没有被使用?
排错步骤
为什么索引没有被使用
是一个涉及面较广的问题。有很多种原因会导致索引没有被使用。下面是一些非常有用的检查列
快速检查
表上是否存在索引?
检查您认为应该通过索引访问的表上是否真的有定义索引。那些索引可能已经被删掉或者在创建的时候就失败了
如一种可能的场景是,在对表做导入或 load 操作后,由于软件或人为错误造成索引没有被创建。下面的语句可以用
来检查索引是否存在。
SELECT index_name FROM user_indexes WHERE table_name = &Table_Name;
索引是否应该被使用?
Oracle 不会仅仅因为有索引存在就一定要使用索引。如果一个查询需要检索出这个表里所有的记录(比如说表之间做
连接操作),那为什么还要既访问索引的所有数据又访问表的所有数据呢?在这种情况下只访问表的数据会更快。对
所有的查询 Oracle Optimizer 会基于统计信息来计算各种访问路径,包括索引,从而选出最优的一个。
索引本身的问题
索引列或者索引的前置列是否在单表(
non-join
)查询的
Where
条件中(
predicate list
)?
如果不是,至少需要索引前置列在查询谓词列表中,查询才能使用索引。(例外:请见下面的 Skip Scan)。
示例:
在列 EMP.EMPNO 上定义了单列索引 EMPNO_I1,同时在列 EMP.EMPNO EMP.DEPT 上定义了联合索引
EMPNO_DEPT_I2EMP.EMPNO为索引前置列)。那么必须在查询谓词列表中(where从句)使用列
EMP.EMPNO,优化器才能使用这两个索引中的某一个。
SELECT ename, sal, deptno FROM emp WHERE empno<100;
例外:
只要索引中包含查询所需的所有列, 而且至少有一个索引列中含有非空约束,CBO 就能够使用索引快速全扫描
(INDEX_FFS)。执行 INDEX_FFS 不需要索引前置列。需要注意的是 INDEX_FFS 不能保证返回的行是排序的。
结果的顺序是与读取索引块的顺序一致的,只有当使用了 'order by' 子句时才能保证结果是排序的。请参照:
文档 1549181.1 https://support.oracle.com/epmos/faces/DocumentDisplay?_a...
2 9 2025/3/6 16:05
Document 344135.1 Ordering of Result Data
Document 70135.1 Index Fast Full Scan Usage To Avoid Full Table Scans
CBO 能使用 Index Skip Scan (INDEX_SS). 执行 INDEX_SS 不需要索引前置列。请参照:
Document 212391.1 Index Skip Scan Feature
CBO 能够选用一个索引来避免排序,但是索引列必须存于在 order by 子句中才可以。
请参照
Document 67409.1 When will an ORDER BY use an Index to Avoid Sorting?
Document 10577.1 Driving ORDER BY using an Index
索引列是否用在连接谓词中(
join predicates
)?
例如,下面这个连接谓词定义了如何在表 emp dept deptno 列上做连接:
emp.deptno = dept.deptno
如果索引列是连接谓词的一部分,那么查询在执行时使用了哪种类型的连接?
哈希/排序合并连接(Hash / Sort Merge Join: 对于哈希连接和排序合并,在连接执行的时候,外部表的信
息还没有获得,因此无法进行对内部表的行检索。它的处理方式是将外部表和内部表分别查询后将结果合并。
哈希连接和排序合并的内部表不能通过连接的索引列单独被访问。这是连接类型的执行机制的限制。嵌套循环
连接有所不同,它们允许通过索引查询内部表的连接列。
嵌套循环连接(Nested Loops Join:嵌套循环连接读取外部表,然后利用所收集的信息访问内部表。该算法
允许对内部表基于索引进行查询。
只有嵌套循环连接(Nested loops join)允许索引在内部表中仅基于连接列进行查找。
另外,连接的顺序(join order)是否允许使用索引?
一个嵌套循环连接的外部表必须已经访问过,才可以在内部表中使用索引。查看 explain plan,以确定哪些访问路径
已经使用。由于这个限制,表的连接顺序是很重要的。
例如:如果我们通过"emp.deptno = dept.deptno"来对 EMP DEPT 做连接,并且在 EMP.DEPTNO 有一个索
引,并假设查询中没有与 EMP.DEPTNO 相关的其他谓词,EMP 是在 DEPT 前被访问,然后没有值可用于在
EMP.DEPTNO 索引中查询。在这种连接顺序下,要想使用这个索引我们只能使用全索引扫描或索引快速全扫描。在
这种情况下,全表扫描(FTS)的成本可能更小。
索引列在
IN
或者多个
OR
语句中?
比如:
emp.deptno IN (10,23,34,....)
emp.deptno = 10
OR emp.deptno = 23
OR emp.deptno = 34
....
文档 1549181.1 https://support.oracle.com/epmos/faces/DocumentDisplay?_a...
3 9 2025/3/6 16:05
of 9
100墨值下载
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文档的来源(墨天轮),文档链接,文档作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。