为什么oracle选择索引完全扫描,然后是索引ROWID访问,而不是完全表扫描?
为什么oracle选择索引完全扫描,然后按索引ROWID进行访问,而不是只进行一个完整的表扫描,这是一个步骤,可以做同样的事情,而且可能更快 甲骨文为何选择为什么oracle选择索引完全扫描,然后是索引ROWID访问,而不是完全表扫描?,oracle,sql-execution-plan,Oracle,Sql Execution Plan,为什么oracle选择索引完全扫描,然后按索引ROWID进行访问,而不是只进行一个完整的表扫描,这是一个步骤,可以做同样的事情,而且可能更快 甲骨文为何选择 | 2 | TABLE ACCESS BY INDEX ROWID | 3 | INDEX FULL SCAN 结束 为了进一步澄清,这是查询和完整执行计划 SELECT EMP_NO, ENAME, SALARY, dname FROM EMP E, DEPT D WHERE E.DEPT_NO=D.DEPT
| 2 | TABLE ACCESS BY INDEX ROWID
| 3 | INDEX FULL SCAN
结束
为了进一步澄清,这是查询和完整执行计划
SELECT EMP_NO, ENAME, SALARY, dname
FROM EMP E, DEPT D
WHERE E.DEPT_NO=D.DEPT_NO;
Execution Plan
----------------------------------------------------------
Plan hash value: 2125045483
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 879 | 35160 | 8 (13)| 00:00:01 |
| 1 | MERGE JOIN | | 879 | 35160 | 8 (13)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 7 | 91 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_PK | 7 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 879 | 23733 | 6 (17)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMP | 879 | 23733 | 5 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
您会注意到优化器在EMP表上选择了完整的表扫描。然后,它使用键EMP.DEPT_NO在DEPT上查找适当的值,因为在这种情况下,查找879次显然比在DEPT上进行全表扫描并进行879*7比较要快(至少在优化器看来是这样) 为了好玩,您可以通过查看USER_表或DBA_表视图来查看这些表最近的统计数据收集情况:
SELECT TABLE_NAME, LAST_ANALYZED
FROM USER_TABLES
WHERE TABLE_NAME IN ('EMP', 'DEPT')
如果你愿意,你可以使用
BEGIN
DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
TABNAME => 'EMP',
CASCADE => TRUE);
DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
TABNAME => 'DEPT',
CASCADE => TRUE);
END;
通常,表格完整扫描必须读取到表格高水位线(即几乎所有分配给表格的块)。如果表中有一个大的删除,那么表中可能有10000个块,大部分是空的,它必须读取这些块 索引是一种更复杂的结构,但索引完全扫描不必处理空块。此外,索引(因为它们只有列的一个子集)往往更小,并且在缓存中停留的时间更长
在您的示例中,从索引访问索引和表的总成本为3。这相当低,可能表格扫描结果是4或5(也很低,但仍然是第二) 仅当索引部分与条件匹配时,才会读取表数据。根据预期的结果集,这样快吗?您可以再显示一点执行计划吗?索引完全扫描的一个可能优势是它按顺序读取数据,这可以避免排序。查询中是否有ORDER BY?我们不知道您正在运行的查询、访问的表或表中的数据,因此无法回答您的问题。您好,我编辑了问题以澄清,感谢您的评论。没有说明它是“使用EMP.DEPT\u NO键在DEPT上查找适当的值”。这是一个索引完全扫描,没有显示任何筛选器,并且是一个后续合并联接
BEGIN
DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
TABNAME => 'EMP',
CASCADE => TRUE);
DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
TABNAME => 'DEPT',
CASCADE => TRUE);
END;